<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"wan-lei8.gitee.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta property="og:type" content="website">
<meta property="og:title" content="程序员西桐">
<meta property="og:url" content="https://wan-lei8.gitee.io/page/2/index.html">
<meta property="og:site_name" content="程序员西桐">
<meta property="og:locale" content="zh_CN">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="https://wan-lei8.gitee.io/page/2/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false,
    lang   : 'zh-CN'
  };
</script>

  <title>程序员西桐</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">程序员西桐</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">但行好事，莫问前程</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content index posts-expand">
            
      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wan-lei8.gitee.io/2022/01/25/%E5%BC%80%E5%8F%91%E5%BF%85%E5%A4%87linux%E5%91%BD%E4%BB%A4%E5%A4%A7%E5%85%A8/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员西桐">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2022/01/25/%E5%BC%80%E5%8F%91%E5%BF%85%E5%A4%87linux%E5%91%BD%E4%BB%A4%E5%A4%A7%E5%85%A8/" class="post-title-link" itemprop="url">开发必备linux命令大全</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-01-25 13:52:39 / 修改时间：15:29:54" itemprop="dateCreated datePublished" datetime="2022-01-25T13:52:39+08:00">2022-01-25</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>我们的服务一般都是在linux系统运行，因此了解一些关于linux命令是必须。接下来将一一详细介绍一些常用的linux的命令</p>
<ul>
<li>文件操作</li>
<li>远程登录与操作</li>
<li>磁盘挂载</li>
<li>进程管理 启动和结束</li>
<li>系统性能参数查看</li>
<li>网络数据抓取</li>
<li>shell 脚本命令</li>
<li>jvm 常用命令</li>
</ul>
<h2 id="1-文件操作命令"><a href="#1-文件操作命令" class="headerlink" title="1 文件操作命令"></a>1 文件操作命令</h2><h3 id="find"><a href="#find" class="headerlink" title="find"></a>find</h3><ul>
<li><p>find 用于在指定目录下查找文件或子目录，如果不指定查找目录，则在当前目录下查找</p>
</li>
<li><p>命令格式：<code>·find path -option [-print] [ -exec/-ok command &#123;&#125; \ ]</code>;</p>
</li>
<li><ul>
<li><strong>「print」</strong>：将匹配的文件输出到标准输出</li>
<li><strong>「exec」</strong>：对匹配的文件作为参数 让 command 命令执行。{} 是匹配文件的占位符</li>
<li><strong>「ok」</strong>: 和 exec 的作用相同，但在执行命令之前，会给出提示，让用户来确定是否执行</li>
</ul>
</li>
</ul>
<figure class="highlight excel"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">常用的option 选项 | 描述</span><br><span class="line">-mount     | 只检查和指定目录在同一个文件系统下的文件，避免列出其它文件系统中的文件</span><br><span class="line">-amin <span class="built_in">n</span>    | 在过去 <span class="built_in">n</span> 分钟内被读取过</span><br><span class="line">-atime <span class="built_in">n</span>   | 在过去 <span class="built_in">n</span> 天内被读取过的文件</span><br><span class="line">-cmin <span class="built_in">n</span>    | 在过去 <span class="built_in">n</span> 分钟内被修改过</span><br><span class="line">-ctime <span class="built_in">n</span>   | 在过去<span class="built_in">n</span>天内被修改过的文件</span><br><span class="line">-gid <span class="built_in">n</span>     | gid 是 <span class="built_in">n</span> 文件。或 -group name， group 名称是 name 的文件</span><br><span class="line">-pid <span class="built_in">n</span>     | pid 是 <span class="built_in">n</span> 的文件</span><br><span class="line">-ipath p   | 路径名称符合 p 的文件。或 -path p，ipath 会忽略大小写</span><br><span class="line">-name name | 文件名称符合 name 的文件。或者-iname name，iname 会忽略大小写</span><br><span class="line">-size <span class="built_in">n</span>    | 文件大小 是 <span class="built_in">n</span> 单位，b 代表 <span class="number">512</span> 位元组的区块，c 表示字元数，k 表示 kilo bytes，w 是二个位元组</span><br><span class="line">-<span class="built_in">type</span> c    | 文件类型是c的文件。<span class="symbol">d:</span> 目录；<span class="symbol">f:</span> 一般文件；<span class="symbol">l:</span> 符号连结；<span class="symbol">s:</span> socket</span><br></pre></td></tr></table></figure>

<ul>
<li>find 示例</li>
</ul>
<figure class="highlight excel"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">~~ 查找 /<span class="built_in">var</span>/<span class="built_in">log</span> 目录中更改时间在 <span class="number">7</span> 日以前的普通文件，并在删除之前询问它们</span><br><span class="line"># <span class="built_in">find</span> /<span class="built_in">var</span>/<span class="built_in">log</span> -<span class="built_in">type</span> f -mtime +<span class="number">7</span> -ok rm &#123;&#125; \;</span><br></pre></td></tr></table></figure>

<h3 id="touch-和-vim"><a href="#touch-和-vim" class="headerlink" title="touch 和 vim"></a>touch 和 vim</h3><ul>
<li><strong>「touch」</strong> 可用于创建一个空文件，如果文件存在，则会更改文件的访问时间和修改时间</li>
<li>touch 示例</li>
</ul>
<figure class="highlight irpf90"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">~~ #创建一个名为“<span class="keyword">file</span>”的新的空白文件，如果存在则会修改其时间属性</span><br><span class="line"># <span class="keyword">touch</span> <span class="keyword">file</span>             </span><br></pre></td></tr></table></figure>

<ul>
<li><strong>「vim」</strong> Vim是从 vi 发展出来的一个文本编辑器，是在 linux 系统交互界面进行文件查看，编写文本的首选工具</li>
</ul>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/GNMLl94I7tekDf9vwC3IDkiagyyec5ibUPXMCaplqAe3zHibNgN57OI6d0vklSwaMbuYoKu4Sg7K2aL9NyExJZn6Q/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">image.png</p>
<ul>
<li>vim 共分为三种模式，分别是命令模式（Command mode），输入模式（Insert mode）和底线命令模式（Last line mode）</li>
</ul>
<figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1</span> 命令模式：用户 vim fileName，便进入了命令模式</span><br><span class="line">    i         切换到输入模式，以输入字符</span><br><span class="line">    :         冒号切换到底线命令模式</span><br><span class="line">    /word     向光标之下寻找一个名称为 word 的字符串</span><br><span class="line">    <span class="string">?w</span>ord     向光标之上寻找一个字符串名称为 word 的字符串</span><br><span class="line">    n         重复前一个搜索（与 / 或 ? 有关）</span><br><span class="line">    N         反向重复前一个搜索（与 / 或 ? 有关）</span><br><span class="line">    PageUp    上翻页</span><br><span class="line">    PageDown  下翻页</span><br><span class="line">    G       移动到这个档案的最后一行(常用)</span><br><span class="line">    nG       n 为数字。移动到这个档案的第 n 行</span><br><span class="line">    </span><br><span class="line"><span class="number">2</span> 输入模式: 在命令模式下按下i就进入了输入模式; ESC 退出输入模式，切换到命令模式</span><br><span class="line">    字符按键、shift组合    输入字符</span><br><span class="line">    ENTER                 回车键，换行</span><br><span class="line">    BACK SPACE            退格键，删除光标前一个字符</span><br><span class="line">    DEL                   删除键，删除光标后一个字符</span><br><span class="line">    方向键                在文本中移动光标</span><br><span class="line">    HOME/<span class="keyword">END</span>              移动光标到行首/行尾</span><br><span class="line">    Page Up/Page Down     上/下翻页</span><br><span class="line">    Insert                切换光标为输入/替换模式，光标将变成竖线/下划线</span><br><span class="line"></span><br><span class="line"><span class="number">3</span> 底线命令模式: 在命令模式下按下 <span class="string">&quot;:&quot;</span> 就进入了底线命令模式; ESC退出模式，切换到命令模式</span><br><span class="line">    <span class="symbol">:q</span>                 退出 vim 程序</span><br><span class="line">    <span class="symbol">:w</span>                 保存文件</span><br><span class="line">    <span class="symbol">:wq</span>                保存后离开</span><br><span class="line">    <span class="symbol">:</span>!q                不保存退出</span><br><span class="line">    <span class="symbol">:w</span> [filename]      将编辑的数据储存成另一个档案</span><br><span class="line">    <span class="symbol">:r</span> [filename]      在编辑的数据中，读入另一个档案的数据。追加到游标所在行后面</span><br><span class="line">    <span class="symbol">:</span>!ShellCommand     暂时离开 vi 到指令行模式下执行 shellCommand 的显示结果</span><br><span class="line">    <span class="symbol">:%s/word1/word2/g</span>  从第一行到最后一行寻找 word1 字符串，并将该字符串取代为 word2 </span><br><span class="line">    <span class="symbol">:%s/word1/word2/gc</span> 和 %s/word1/word2/g 功能一致，不过每次替换都需用户确认  </span><br></pre></td></tr></table></figure>

<h3 id="less、cat、more、tail-和-head"><a href="#less、cat、more、tail-和-head" class="headerlink" title="less、cat、more、tail 和 head"></a>less、cat、more、tail 和 head</h3><ul>
<li><strong>「less」</strong> 是linux 必不可少的查看文件工具，功能极其强大</li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">less [option] 文件</span><br><span class="line">option 常用参数</span><br><span class="line"><span class="deletion">-f 强制打开文件，二进制文件显示时，不提示警告；</span></span><br><span class="line"><span class="deletion">-i 搜索时忽略大小写；除非搜索串中包含大写字母；</span></span><br><span class="line"><span class="deletion">-I 搜索时忽略大小写，除非搜索串中包含小写字母；</span></span><br><span class="line"><span class="deletion">-m 显示读取文件的百分比；</span></span><br><span class="line"><span class="deletion">-M 显法读取文件的百分比、行号及总行数；</span></span><br><span class="line"><span class="deletion">-N 在每行前输出行号；</span></span><br><span class="line"><span class="deletion">-p pattern 搜索 pattern；比如在/etc/profile搜索单词MAIL，就用 less -p MAIL /etc/profile</span></span><br><span class="line"><span class="deletion">-s 把连续多个空白行作为一个空白行显示；</span></span><br></pre></td></tr></table></figure>

<ul>
<li>less 文件后可进行的动作操作和 vim 在命令模式下的操作相似；less在查看文本时的常用动作命令如下</li>
</ul>
<figure class="highlight coq"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">Enter      向下移动一行</span><br><span class="line">y          向上移动一行</span><br><span class="line">Space      向下滚动一屏</span><br><span class="line">b          向上滚动一屏</span><br><span class="line">d          向下滚动半屏</span><br><span class="line">u          向上滚动半屏</span><br><span class="line">g          跳到第一行</span><br><span class="line">G          跳到最后一行</span><br><span class="line">/<span class="built_in">pattern</span>   向下搜索<span class="built_in">pattern</span> ，比如 /MAIL 表示在文件中搜索MAIL单词</span><br><span class="line">?<span class="built_in">pattern</span>   向上搜索<span class="built_in">pattern</span> </span><br><span class="line">n          重复前一个搜索（与 / 有关）</span><br><span class="line">N          反向重复前一个搜索（与 / 有关）</span><br><span class="line">v          调用 vi 编辑器</span><br><span class="line">q          退出 less</span><br><span class="line">!command   调用 shell 命令；比如 !ls 显示当前目录下的所有文件</span><br></pre></td></tr></table></figure>

<ul>
<li><strong>「more」</strong> 常用于显示输出的内容，然后根据窗口的大小进行分页显示，然后还能提示文件的百分比。命令格式：<code>more 文件</code>，more 常用操作指令如下</li>
</ul>
<figure class="highlight excel"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Enter        向下<span class="built_in">n</span>行，需要定义，默认为<span class="number">1</span>行；</span><br><span class="line">Ctrl+f       向下滚动一屏</span><br><span class="line">空格键        向下滚动一屏</span><br><span class="line">Ctrl+b       返回上一屏</span><br><span class="line">=            输出当前行的行号</span><br><span class="line"><span class="symbol">:f</span>           输出文件名和当前行的行号</span><br><span class="line">v            当我们查看某一文件时，想调用vi来编辑它，用 v 动作指令</span><br><span class="line">!command     调用 shell，并执行command命令</span><br><span class="line">q            退出 more</span><br></pre></td></tr></table></figure>

<ul>
<li><strong>「cat」</strong> 常用于连接文件并打印到标准输出设备上，也可用于查看文件。格式：<code>cat fileName [| command ]</code> ，command 默认是 echo，cat会一次性显示整个文件的内容，不分页</li>
<li><strong>「head」</strong> 是显示一个文件的内容的前多少行；常用命令格式：<code>head -n 行数值 文件名</code></li>
<li><strong>「tail」</strong> 是显示一个文件的内容的后多少行；常用命令格式：<code>tail -n 行数值 文件名</code></li>
</ul>
<h3 id="grep、zgrep"><a href="#grep、zgrep" class="headerlink" title="grep、zgrep"></a>grep、zgrep</h3><ul>
<li>grep 一般用于在文件中查和匹配模式匹配的每一行数据。命令格式 <code>grep [options] &#39;pattern&#39; [files]</code>；grep 支持处理管道的输出数据；pattern 支持正则表达式；files 可以是多个文件，用空格分开</li>
<li>grep 无法在压缩文件匹配查找数，此时可以用 zgrep，zgrep 适用处理压缩后的gz等格式文件</li>
</ul>
<figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">options选项 <span class="string">| 功能描述</span></span><br><span class="line">-i <span class="string">| 忽略大小写</span></span><br><span class="line">-v <span class="string">| 不匹配匹配的</span></span><br><span class="line">-l <span class="string">| 输出匹配的文件名</span></span><br><span class="line">-L <span class="string">| 输出不匹配的文件名</span></span><br><span class="line">-c <span class="string">| 输出匹配的数目（行数）</span></span><br><span class="line">-C num  <span class="string">|       输出匹配的前后 num 条行数</span></span><br><span class="line">-n <span class="string">| 输出匹配行的同时在前面加上文件名及在文件名中的行数</span></span><br></pre></td></tr></table></figure>

<ul>
<li>grep 和 zgrep 示例</li>
</ul>
<figure class="highlight vim"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">~~ 输出匹配 lwl 数据，及前后十行</span><br><span class="line"># <span class="keyword">grep</span> -C <span class="number">10</span> <span class="string">&#x27;lwl&#x27;</span> <span class="built_in">log</span>.txt </span><br></pre></td></tr></table></figure>

<h3 id="cp"><a href="#cp" class="headerlink" title="cp"></a>cp</h3><ul>
<li>文件目录复制可用使用 cp 命令。cp 格式：<code>cp [选项参数] fileSource... fileTarget</code></li>
</ul>
<figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">cp 选项参数 <span class="string">| 描述</span></span><br><span class="line">-a <span class="string">| 此选项通常在复制目录时使用，它保留链接、文件属性，并复制目录下的所有内容</span></span><br><span class="line">-r <span class="string">| 若给出的源文件是一个目录文件，此时将复制该目录下所有的子目录和文件</span></span><br><span class="line">-f <span class="string">| 覆盖已经存在的目标文件而不给出提示。</span></span><br><span class="line">-i <span class="string">| 与 -f 选项相反，在覆盖目标文件之前给出提示，要求用户确认是否覆盖，回答 y 时目标文件将被覆盖</span></span><br><span class="line">-l <span class="string">| 不复制文件，只是生成链接文件</span></span><br></pre></td></tr></table></figure>

<ul>
<li>cp 示例</li>
</ul>
<figure class="highlight excel"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">~~ 将当前目录 <span class="built_in">csc</span>/ 下的所有文件复制到新目录 lwl 下</span><br><span class="line"># cp –r <span class="built_in">csc</span>/ lwl </span><br></pre></td></tr></table></figure>

<h3 id="mv"><a href="#mv" class="headerlink" title="mv"></a>mv</h3><ul>
<li>mv 可用来移动文件夹、文件 或者 修改文件名、目录名</li>
</ul>
<figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">option 参数 <span class="string">| 描述</span></span><br><span class="line">-b <span class="string">| 当目标文件存在时，先进行备份再覆盖</span></span><br><span class="line">-f <span class="string">| 当目标文件存在时，强制覆盖</span></span><br><span class="line">-i <span class="string">| 默认选项，当目标文件存在时，提示是否覆盖</span></span><br><span class="line">-t <span class="string">| 先指定目标，再指定源目标。即目标 和 源目标 参数位置互换</span></span><br></pre></td></tr></table></figure>

<ul>
<li>mv 示例</li>
</ul>
<figure class="highlight maxima"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">~~ 把 <span class="built_in">csc</span>.txt 修改名字为 lwl.txt</span><br><span class="line"># mv <span class="built_in">csc</span>.txt lwl.txt</span><br><span class="line">~~ 将 <span class="built_in">csc</span> 目录下的文件移到 lwl 下</span><br><span class="line"># mv <span class="built_in">csc</span>/ lwl </span><br></pre></td></tr></table></figure>

<h3 id="rm"><a href="#rm" class="headerlink" title="rm"></a>rm</h3><ul>
<li>rm 命令用于删除一个文件或者目录；命令格式 <code>rm [options] fileName/filePath</code></li>
</ul>
<figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">option参数 <span class="string">| 描述</span></span><br><span class="line">-i <span class="string">| 删除前逐一询问确认</span></span><br><span class="line">-f <span class="string">| 即使原档案属性设置为只读，也可强制删除，无需确认</span></span><br><span class="line">-r <span class="string">| 将目录及以下之档案亦逐一删除</span></span><br></pre></td></tr></table></figure>

<ul>
<li>rm 示例</li>
</ul>
<figure class="highlight stata"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">~~ 删除文件名 <span class="keyword">test</span>.txt</span><br><span class="line"># <span class="keyword">rm</span>  -rf   <span class="keyword">test</span>.txt</span><br></pre></td></tr></table></figure>

<h3 id="mdkir"><a href="#mdkir" class="headerlink" title="mdkir"></a>mdkir</h3><ul>
<li>mdkir命令用于创建目录,  <code>mkdir [-p] dirName</code>；-p 确保目录名称存在，不存在的就建一个</li>
</ul>
<h3 id="tar-和-jar"><a href="#tar-和-jar" class="headerlink" title="tar 和 jar"></a>tar 和 jar</h3><ul>
<li>tar 的命令格式：<code>tar [-option] fileName/filePath</code>；tar具有打包和压缩功能，普通文件和文件夹可以被打包成 xxx.tar，如果要压缩，则是在打包之后再压缩，格式是 xxx.tar.gz</li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">tar [-cxtzjvfpPN] 文件与目录</span><br><span class="line">常用参数：描述</span><br><span class="line"><span class="deletion">-c ：建立一个压缩文件 </span></span><br><span class="line"><span class="deletion">-x ：解开一个压缩文件</span></span><br><span class="line"><span class="deletion">-t ：查看tarfile 里面的文件！特别注意，c/x/t 仅能存在一个，不可同时存在</span></span><br><span class="line"><span class="deletion">-z ：用 gzip 解压缩</span></span><br><span class="line"><span class="deletion">-j ：用 bzip2 解压缩</span></span><br><span class="line"><span class="deletion">-v ：压缩的过程中显示文件，这个常用，但不建议用</span></span><br><span class="line"><span class="deletion">-f ：使用档名，在 f 之后要立即接档名！例如使用『 tar -zcfv tfile sfile』就是错误的写法，要写成 『tar -zcvf tfile sfile』才对喔</span></span><br><span class="line"><span class="deletion">-p ：使用原文件的原来属性（属性不会依据使用者而变）</span></span><br><span class="line"><span class="deletion">-P ：（大写P）使用绝对路径来压缩</span></span><br><span class="line"><span class="deletion">-r : 新增文件到已存在的备份文件的结尾部分</span></span><br><span class="line"><span class="deletion">-N ：比后面接的日期(yyyy/mm/dd)还要新的才会被打包进新建的文件中</span></span><br><span class="line"><span class="deletion">--exclude file ：在压缩的过程中，不要将 FILE 打包</span></span><br></pre></td></tr></table></figure>

<ul>
<li>tar 示例</li>
</ul>
<figure class="highlight vala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">~~ 打包不压缩：/home/lwl 目录</span><br><span class="line"><span class="meta"># tar -cvf lwl.tar /home/lwl</span></span><br><span class="line">~~ 打包并压缩：/home/lwl 目录</span><br><span class="line"><span class="meta"># tar zcvf lwl.tar.gz /home/lwl</span></span><br><span class="line">~~ 解压 lwl.tar.gz</span><br><span class="line"><span class="meta"># tar zxvf lwl.tar.gz</span></span><br><span class="line"></span><br><span class="line">~~ 压缩 lwl.java 为 bz2 格式</span><br><span class="line"><span class="meta"># tar jcvf lwl.tar.bz2 lwl.java</span></span><br><span class="line">~~ 解压 lwl.tar.bz2</span><br><span class="line"><span class="meta"># tar jxvf lwl.tar.bz2</span></span><br><span class="line"></span><br><span class="line">~~ 解压部分文件 log2021.log</span><br><span class="line"><span class="meta"># tar -zxvf log.tar.gz log2021.log</span></span><br></pre></td></tr></table></figure>

<ul>
<li>jar 的命令格式：<code>jar &#123;c t x u f &#125;[ v m e 0 M i ][-C 目录] fileName</code>；其中{ ctxu }这四个选项必须选其一。[ v f m e 0 M i ]是可选选项，文件名是必须的</li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">jar &#123;c t x u f &#125;[ v m e 0 M i ][-C 目录] fileName </span><br><span class="line">jar 的选项参数和 tar 差不多，如下</span><br><span class="line"></span><br><span class="line"><span class="deletion">-c ：创建一个jar包</span></span><br><span class="line"><span class="deletion">-t ：显示jar中的内容列表</span></span><br><span class="line"><span class="deletion">-x ：解压jar包</span></span><br><span class="line"><span class="deletion">-u ：添加文件到jar包中</span></span><br><span class="line"><span class="deletion">-f ：指定jar包的文件名</span></span><br><span class="line"><span class="deletion">-v ：生成详细的报造，并输出至标准设备</span></span><br><span class="line"><span class="deletion">-m ：指定manifest.mf文件.(manifest.mf 文件中可以对jar包及其中的内容作一些一设置)</span></span><br><span class="line"><span class="deletion">-0 ：产生jar包时不对其中的内容进行压缩处理</span></span><br><span class="line"><span class="deletion">-M ：不产生所有文件的清单文件(Manifest.mf)。这个参数会忽略掉 -m 参数的设置</span></span><br><span class="line"><span class="deletion">-i ：为指定的jar文件创建索引文件</span></span><br><span class="line"><span class="deletion">-C ：表示转到相应的目录下执行jar命令，相当于cd到那个目录，然后不带-C执行jar命令</span></span><br></pre></td></tr></table></figure>

<ul>
<li>jar 示例</li>
</ul>
<figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">~~ 利用hello目录创建 hello.<span class="keyword">jar </span>包，并显示创建过程</span><br><span class="line"><span class="comment"># jar cvf hello.jar hello</span></span><br><span class="line">~~ 往 <span class="keyword">jar </span>包添加文件，将 HelloWorld.<span class="keyword">java </span>添加到 hello.<span class="keyword">jar </span>包中</span><br><span class="line"><span class="comment"># jar uf hello.jar HelloWorld.java    </span></span><br><span class="line">~~  解压 hello.<span class="keyword">jar </span>至当前目录</span><br><span class="line"><span class="comment"># jar xvf hello.jar  </span></span><br></pre></td></tr></table></figure>

<h3 id="chmod"><a href="#chmod" class="headerlink" title="chmod"></a>chmod</h3><ul>
<li>chmod 是控制用户对文件的权限的命令， 命令格式：<code>chmod [-cfvR] mode file</code><img src="https://mmbiz.qpic.cn/mmbiz_png/GNMLl94I7tekDf9vwC3IDkiagyyec5ibUPhuWqkiciaB2jwlPnFjro1hXqe2kfalibUMyFNpAykeM84kXphhCejaibYw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></li>
</ul>
<figure class="highlight asciidoc"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">## -cfvR 参数解析</span><br><span class="line">-c : 若该文件权限确实已经更改，才显示其更改动作</span><br><span class="line">-f : 若该文件权限无法被更改也不要显示错误讯息</span><br><span class="line">-v : 显示权限变更的详细资料</span><br><span class="line">-R : 对目前目录下的所有文件与子目录进行相同的权限变更(即以递归的方式逐个变更)</span><br><span class="line"></span><br><span class="line">## mode [ugoa][+-=][rwxX-] 参数解析</span><br><span class="line">u 表示该文件的拥有者</span><br><span class="line">g 表示与该文件的拥有者属于同一个群体(group)者</span><br><span class="line">o 表示其他以外的人</span><br><span class="line">a 包扣 u g o</span><br><span class="line">## [+-=]</span><br><span class="line">+ 表示增加权限</span><br><span class="line"><span class="bullet">- </span>表示取消权限</span><br><span class="line"><span class="section">= 表示唯一设定权限</span></span><br><span class="line">## [rwxX-]</span><br><span class="line">r 表示可读取</span><br><span class="line">w 表示可写入</span><br><span class="line">x 表示可执行</span><br><span class="line">X 只有当文件为目录文件，或者其他类型的用户有可执行权限时，才将文件权限设置可执行</span><br><span class="line"><span class="bullet">- </span>不具任何权限</span><br></pre></td></tr></table></figure>

<ul>
<li>chmod 示例</li>
</ul>
<figure class="highlight vala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"># chmod ugo+r lwl.txt</span></span><br><span class="line"><span class="meta"># chmod ug+w,o-w csc.txt lwl.txt</span></span><br></pre></td></tr></table></figure>

<h3 id="ln"><a href="#ln" class="headerlink" title="ln"></a>ln</h3><ul>
<li>命令格式：<code>ln [options] [源文件或目录] [目标文件或目录]</code>；当我们需要在不同的目录，用到相同的文件时，又不想浪费空间复制相同的文件，可以用ln 链接它，相当创建一个快捷图标</li>
</ul>
<figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">options 参数 <span class="string">| 描述</span></span><br><span class="line">-b <span class="string">| 删除，覆盖以前建立的链接</span></span><br><span class="line">-d <span class="string">| 允许超级用户制作目录的硬链接</span></span><br><span class="line">-f <span class="string">| 强制执行</span></span><br><span class="line">-i <span class="string">| 交互模式，文件存在则提示用户是否覆盖</span></span><br><span class="line">-n <span class="string">| 把符号链接视为一般目录</span></span><br><span class="line">-s <span class="string">| 软链接(符号链接)</span></span><br></pre></td></tr></table></figure>

<ul>
<li>软链接：以路径的形式存在。类似于Windows操作系统中的快捷方式；可以对一个不存在的文件名进行链接；可以对目录进行链接；软链接可以 跨文件系统 ，硬链接不可以</li>
<li>硬链接：以文件副本的形式存在。但不占用实际空间；不允许给目录创建硬链接；硬链接只有在同一个文件系统中才能创建</li>
<li>ln 示例</li>
</ul>
<figure class="highlight gcode"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">~~ 给文件创建软链接，lo<span class="name">g2021.</span>log文件创建软链接lo<span class="name">g2021</span>，如果lo<span class="name">g2021.</span>log丢失，lo<span class="name">g2021</span>将失效</span><br><span class="line"><span class="attr"># ln -s log2021</span>.log li<span class="symbol">nk2021</span></span><br></pre></td></tr></table></figure>

<h2 id="2-远程登录与操作"><a href="#2-远程登录与操作" class="headerlink" title="2 远程登录与操作"></a>2 远程登录与操作</h2><h3 id="ssh"><a href="#ssh" class="headerlink" title="ssh"></a>ssh</h3><ul>
<li>linux下的ssh服务是一个守护进程(demon)，ssh 服务端的进程名为 sshd ，负责实时监听客户端的请求（默认22端口），包括公共秘钥等交换等信息。ssh的客户端可以用 xShell，Securecrt, Mobaxterm等工具进行连接，也可以在 linux 命令窗口使用 ssh 命令连接 ssh 服务端</li>
<li>命令格式:<code>ssh [-p port] user@remoteIp</code> 或者 <code>ssh [-p port] user@remoteIp shellCommand</code>; 会提示输入密码</li>
<li>ssh示例</li>
</ul>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">~~ 登录 <span class="number">192.168</span>.<span class="number">25.137</span> ，并执行 ls <span class="regexp">/backup/</span>data</span><br><span class="line"># ssh root@<span class="number">192.168</span>.<span class="number">25.137</span> ls <span class="regexp">/backup/</span>data</span><br></pre></td></tr></table></figure>

<h3 id="sftp"><a href="#sftp" class="headerlink" title="sftp"></a>sftp</h3><ul>
<li>登录sftp服务器 <code>sftp -oPort=23 user@remoteIp</code></li>
</ul>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">~~ 上传，第一个目录是本机的， 第二个参数远端的    </span><br><span class="line">&gt; put <span class="regexp">/etc/</span>hosts <span class="regexp">/home/</span>lwl   </span><br><span class="line">~~ 下载，第一个目录是远端的， 第二个参数是本机的</span><br><span class="line">&gt; get <span class="regexp">/home/</span>lwl <span class="regexp">/home/</span>csc  </span><br></pre></td></tr></table></figure>

<h3 id="scp"><a href="#scp" class="headerlink" title="scp"></a>scp</h3><ul>
<li>如果是涉及不同linux系统间的文件复制则用 scp, 格式: <code>scp [options] fileSource fileTarget</code></li>
</ul>
<figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">options 选项参数 <span class="string">| 描述</span></span><br><span class="line"></span><br><span class="line">-P <span class="string">| port：注意是大写的P, port是指定数据传输用到的端口号</span></span><br><span class="line">-p <span class="string">| 保留原文件的修改时间，小写p，访问时间和访问权限</span></span><br><span class="line">-r <span class="string">| 递归复制整个目录</span></span><br><span class="line">-C <span class="string">| 允许压缩。（将-C标志传递给ssh，从而打开压缩功能）</span></span><br></pre></td></tr></table></figure>

<ul>
<li>scp 示例</li>
</ul>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">~~ 从本地复制到远程 </span><br><span class="line">~~ A 格式: scp localFile username@remoteIp:filePath; B 格式：scp localFile remoteIp:filePath </span><br><span class="line">~~ A 命令指定了用户名，但命令执行后需要输入密码，B 格式则需要输入用户名和密码</span><br><span class="line"># scp -r <span class="regexp">/home/</span>lwl<span class="regexp">/ root@www.csc.com:/</span>home<span class="regexp">/lwl/</span> </span><br><span class="line"></span><br><span class="line">~~ 从远程复制到本地 </span><br><span class="line">~~ 格式：scp remoteIp:filePath localFile</span><br><span class="line"># scp -r www.csc.com:<span class="regexp">/home/</span>lwl<span class="regexp">/ /</span>home<span class="regexp">/lwl/</span></span><br></pre></td></tr></table></figure>

<h3 id="文件同步-rsync"><a href="#文件同步-rsync" class="headerlink" title="文件同步 rsync"></a>文件同步 rsync</h3><ul>
<li>与其他文件传输工具（如 FTP 或 scp）不同，和 scp 功能类似。rsync 的最大特点是会检查发送方和接收方已有的文件</li>
</ul>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> rsync -r <span class="built_in">source</span> destination</span></span><br></pre></td></tr></table></figure>

<h3 id="linux与客户端的上传下载命令：rz、sz"><a href="#linux与客户端的上传下载命令：rz、sz" class="headerlink" title="linux与客户端的上传下载命令：rz、sz"></a>linux与客户端的上传下载命令：rz、sz</h3><ul>
<li>用 ssh 管理 linux 服务器时经常需要远程与 win 本地之间交互文件。直接用SecureCRT自带的上传下载功能无疑是最方便的。上传：rz、下载：sz</li>
<li>在 window 上使用SecureCRT、XShell 软件，用 rz、sz 进行上传下载</li>
</ul>
<figure class="highlight vala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">~~ 上传文件到linux；弹出SecureCRT上传窗口，用SecureCRT来上传</span><br><span class="line"><span class="meta"># rz    </span></span><br><span class="line">~~ 下载文件到客户端（window）</span><br><span class="line"><span class="meta"># sz filename</span></span><br></pre></td></tr></table></figure>

<h2 id="3-磁盘挂载"><a href="#3-磁盘挂载" class="headerlink" title="3 磁盘挂载"></a>3 磁盘挂载</h2><h3 id="df"><a href="#df" class="headerlink" title="df"></a>df</h3><ul>
<li>df 用于查看磁盘空间占用情况：<code>df [-options] [file]</code></li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">options 参数解释</span><br><span class="line"></span><br><span class="line"><span class="deletion">-i                   显示inode信息</span></span><br><span class="line"><span class="deletion">-h                   方便阅读方式显示</span></span><br><span class="line"><span class="deletion">-k                   区块为1024字节</span></span><br><span class="line"><span class="deletion">-m                   区块为1048576字节</span></span><br><span class="line"><span class="deletion">-a                   全部文件系统列表</span></span><br><span class="line"><span class="deletion">-T                   显示文件系统类型</span></span><br><span class="line"><span class="deletion">-t&lt;文件系统类型&gt;      只显示选定文件系统的磁盘信息</span></span><br><span class="line"><span class="deletion">-x&lt;文件系统类型&gt;      不显示选定文件系统的磁盘信息</span></span><br></pre></td></tr></table></figure>

<ul>
<li>df 示例</li>
</ul>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># df -hT</span></span><br><span class="line">文件系统          类型            容量  已用  可用 已用% 挂载点</span><br><span class="line">devtmpfs          devtmpfs         <span class="number">63</span>G     <span class="number">0</span>   <span class="number">63</span>G    <span class="number">0</span>% /dev</span><br><span class="line">tmpfs             tmpfs            <span class="number">63</span>G     <span class="number">0</span>   <span class="number">63</span>G    <span class="number">0</span>% <span class="regexp">/dev/</span>shm</span><br><span class="line">tmpfs             tmpfs            <span class="number">63</span>G  <span class="number">4.1</span>G   <span class="number">59</span>G    <span class="number">7</span>% /run</span><br><span class="line">tmpfs             tmpfs            <span class="number">63</span>G     <span class="number">0</span>   <span class="number">63</span>G    <span class="number">0</span>% <span class="regexp">/sys/</span>fs/cgroup</span><br></pre></td></tr></table></figure>

<h3 id="mount"><a href="#mount" class="headerlink" title="mount"></a>mount</h3><ul>
<li>mount 命令是经常会使用到的命令，它用于挂载Linux系统外的文件</li>
</ul>
<figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">命令格式：<span class="built_in">mount</span> [-<span class="type">t</span> <span class="type">vfstype</span>] [-<span class="type">o</span> <span class="type">options</span>] device <span class="built_in">dir</span></span><br><span class="line"><span class="number">1</span>、<span class="literal">-t</span> vfstype 指定文件系统的类型，通常不必指定，<span class="built_in">mount</span> 会自动选择正确的类型</span><br><span class="line">iso9660 : 光盘或光盘镜像 </span><br><span class="line">msdos   : DOS fat16文件系统 </span><br><span class="line">vfat    : Windows <span class="number">9</span>x fat32文件系统</span><br><span class="line">ntfs    : Windows NT ntfs文件系统</span><br><span class="line">smbfs   : <span class="built_in">Mount</span> Windows文件网络共享</span><br><span class="line">nfs     ：UNIX(LINUX) 文件网络共享</span><br><span class="line"></span><br><span class="line"><span class="number">2</span>、<span class="literal">-o</span> options 主要用来描述设备或档案的挂接方式</span><br><span class="line">loop      ：用来把一个文件当成硬盘分区挂接上系统 </span><br><span class="line">ro        ：采用只读方式挂接设备 </span><br><span class="line">rw        ：采用读写方式挂接设备 </span><br><span class="line">iocharset ：指定访问文件系统所用字符集</span><br><span class="line"></span><br><span class="line"><span class="number">3</span>、device 要挂接(<span class="built_in">mount</span>)的设备</span><br><span class="line"></span><br><span class="line"><span class="number">4</span>、<span class="built_in">dir</span>设备在系统上的挂接点(<span class="built_in">mount</span> point)</span><br></pre></td></tr></table></figure>

<ul>
<li>mount 示例</li>
</ul>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">~~ <span class="number">1</span> 挂接U盘,<span class="regexp">/dev/</span>sdd1 是 U 盘里的磁盘分区</span><br><span class="line"># mount -t vfat -o iocharset=cp936 <span class="regexp">/dev/</span>sdd1 <span class="regexp">/mnt/u</span>sb</span><br><span class="line"></span><br><span class="line">~~ <span class="number">2</span> 挂接Windows文件共享</span><br><span class="line">~~ administrator 和 pldy123 是ip地址为<span class="number">10.140</span>.<span class="number">133.23</span> windows计算机的一个用户名和密码，c$ 是这台计算机的一个磁盘共享</span><br><span class="line"># mount -t smbfs -o username=administrator,password=pldy123 <span class="comment">//10.140.133.23/c$ /mnt/samba</span></span><br><span class="line"></span><br><span class="line">~~ <span class="number">3</span> linux 挂接(mount)其他linux系统 NFS 共享 </span><br><span class="line"><span class="regexp">/export/</span>home<span class="regexp">/sunky 10.140.133.23(rw)  ~~ 在服务端 /</span>etc/exports文件配置共享目录</span><br><span class="line">~~ 在服务端启动 nfs 服务</span><br><span class="line"><span class="regexp">/etc/</span>rc.d<span class="regexp">/init.d/</span>nfs start 启动NFS服务 </span><br><span class="line"><span class="regexp">/etc/</span>rc.d<span class="regexp">/init.d/</span>nfs stop 停止NFS服务</span><br><span class="line">~~ linux 客户端挂接 NFS 共享</span><br><span class="line"># mount -t nfs -o rw <span class="number">10.140</span>.<span class="number">133.9</span>:<span class="regexp">/export/</span>home<span class="regexp">/sunky /m</span>nt/nfs</span><br></pre></td></tr></table></figure>

<h2 id="4-进程管理-启动和结束"><a href="#4-进程管理-启动和结束" class="headerlink" title="4 进程管理 启动和结束"></a>4 进程管理 启动和结束</h2><h3 id="systemctl-和-service"><a href="#systemctl-和-service" class="headerlink" title="systemctl 和 service"></a>systemctl 和 service</h3><ul>
<li><strong>「service」</strong> 命令本身是一个shell脚本，它会在 /etc/init.d/ 目录查找指定的服务脚本，然后调用该服务脚本来完成任务；service命令用于对系统服务进行管理，比如启动（start）、停止（stop）、重启（restart）、查看状态（status）等。命令格式：<code>service 服务名 [start|stop|restart|reload|status]</code></li>
</ul>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">~~ service 命令: 停止、启动、查看 redis服务</span><br><span class="line"># service redis stop   ~~ 等于在 <span class="regexp">/etc/i</span>nit.d<span class="regexp">/ 目录下运行 ./</span>redis stop</span><br><span class="line"># service redis start  ~~ 等于在 <span class="regexp">/etc/i</span>nit.d<span class="regexp">/ 目录下运行 ./</span>redis start</span><br><span class="line"># service redis status ~~ 等于在 <span class="regexp">/etc/i</span>nit.d<span class="regexp">/ 目录下运行 ./</span>redis status</span><br></pre></td></tr></table></figure>

<ul>
<li><strong>「systemctl」</strong> 命令兼容了 service 命令，且包含其他更强大功能</li>
<li>systemctl 用来管理 linux系统的多种资源：系统服务、硬件设备、挂载点、socket等；下面则主要介绍关于 service 系统服务的相关命令使用。因为 systemctl 一般用于实现服务自启动的脚本</li>
</ul>
<figure class="highlight vala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">~~ 系统自启动时 启动 cron 服务，启用或禁用它</span><br><span class="line"><span class="meta"># systemctl enable crond.service</span></span><br><span class="line"><span class="meta"># systemctl disable ccrond.service</span></span><br><span class="line"><span class="meta"># systemctl is-active crond.service  ~~ 是否正在运行</span></span><br><span class="line"><span class="meta"># systemctl is-enabled crond.service ~~  是否建立了启动链接</span></span><br><span class="line"></span><br><span class="line">~~ 启动、重启、停止、重载、杀死服务以及查看服务 httpd</span><br><span class="line"><span class="meta"># systemctl start httpd.service</span></span><br><span class="line"><span class="meta"># systemctl restart httpd.service</span></span><br><span class="line"><span class="meta"># systemctl stop httpd.service</span></span><br><span class="line"><span class="meta"># systemctl reload httpd.service</span></span><br><span class="line"><span class="meta"># systemctl status httpd.service</span></span><br><span class="line"><span class="meta"># systemctl kill apache.service</span></span><br><span class="line"></span><br><span class="line">~~ 列出所有服务（包括启用的和禁用的）</span><br><span class="line"><span class="meta"># systemctl list-units      ~~  列出所有管理的资源单元</span></span><br><span class="line"><span class="meta"># systemctl list-unit-files --type=service   ~~ 只列出所有 service 类型资源</span></span><br><span class="line"></span><br><span class="line">~~ 获取某个服务（httpd）的依赖性列表</span><br><span class="line"><span class="meta"># systemctl list-dependencies httpd.service</span></span><br><span class="line"></span><br><span class="line">~~ 检查 httpd 服务的所有配置细节</span><br><span class="line"><span class="meta"># systemctl show httpd</span></span><br></pre></td></tr></table></figure>

<ul>
<li>xxx.service 文件的详细配置介绍请上网自行查看，下面给个简单的模板介绍</li>
</ul>
<figure class="highlight avrasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">[Unit]</span><br><span class="line"><span class="symbol">Description:</span>描述</span><br><span class="line">After：auditd.service 在auditd.service启动后才启动</span><br><span class="line"><span class="symbol">ConditionPathExists:</span> 执行条件</span><br><span class="line"></span><br><span class="line">[Service]</span><br><span class="line"><span class="symbol">EnvironmentFile:</span> 变量所在文件</span><br><span class="line"><span class="symbol">ExecStart:</span> 执行启动命令</span><br><span class="line"><span class="symbol">Restart:</span> fail时重启</span><br><span class="line"></span><br><span class="line">[Install]</span><br><span class="line"><span class="symbol">Alias:</span>服务别名</span><br><span class="line"><span class="symbol">WangtedBy:</span> 多用户模式下需要的</span><br></pre></td></tr></table></figure>

<h3 id="nohup-和-amp"><a href="#nohup-和-amp" class="headerlink" title="nohup 和 &amp;"></a>nohup 和 &amp;</h3><ul>
<li>nohup 和 &amp; 组合可以不挂断地在后台运行进程，命令格式：<code>nohup command [agrs..] [&amp;]</code>。&amp; 表示程序可以在linux 后台运行，在当前 shell 界面 <code>ctrl C</code> 退出，该程序也能继续运行，它可以忽略 SIGINT 信号，不过它会随着 shell 程序的关闭而停止，这是因为 &amp; 运行的进程对 SIGHUP 信号不免疫</li>
<li>加上 nohup 就可以做到忽略SIGHUP信号</li>
</ul>
<figure class="highlight vim"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">~~ 在后台运行 lwl.<span class="keyword">py</span>，且不随着 <span class="keyword">shell</span> 关闭而死亡。永远存在</span><br><span class="line"># nohup <span class="keyword">python</span> lwl.<span class="keyword">py</span> &amp;&gt; /var/<span class="built_in">log</span>/lwl.<span class="built_in">log</span> &amp;</span><br></pre></td></tr></table></figure>

<h3 id="kill"><a href="#kill" class="headerlink" title="kill"></a>kill</h3><ul>
<li>如果在linux遇到需要杀死或停止某进程，可以使用 kill, 示例：<code># kill -9 1211</code>。kill 也不单单用于停止进程，可用<code>kill [-s &lt;指定信号&gt;][程序]</code> 发送指定信号给指定程序，而<code># kill -l</code> 可列出全部的信号名称。</li>
</ul>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">~~ 列出全部的信息名称</span><br><span class="line"><span class="meta">#</span><span class="bash"> <span class="built_in">kill</span> -l</span> </span><br><span class="line">1) SIGHUP     2) SIGINT     3) SIGQUIT     4) SIGILL     5) SIGTRAP</span><br><span class="line">6) SIGABRT     7) SIGBUS     8) SIGFPE     9) SIGKILL    10) SIGUSR1</span><br><span class="line">11) SIGSEGV    12) SIGUSR2    13) SIGPIPE    14) SIGALRM    15) SIGTERM</span><br><span class="line">...</span><br><span class="line">...</span><br><span class="line">~~ 发送 SIGQUIT 给 pid = 1211 的进程</span><br><span class="line"><span class="meta">#</span><span class="bash"> <span class="built_in">kill</span> -s SIGQUIT 1211  ~~ 或者 <span class="built_in">kill</span> -SIGQUIT 1211</span></span><br></pre></td></tr></table></figure>

<h2 id="5-系统性能参数查看"><a href="#5-系统性能参数查看" class="headerlink" title="5 系统性能参数查看"></a>5 系统性能参数查看</h2><h3 id="ps"><a href="#ps" class="headerlink" title="ps"></a>ps</h3><ul>
<li>ps 命令用于显示当前进程的状态。命令格式：<code>ps [options]</code></li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">options 参数解释</span><br><span class="line"><span class="deletion">-A/a      列出所有的进程</span></span><br><span class="line"><span class="deletion">-e        等于 “-A”</span></span><br><span class="line">f         显示程序间的关系</span><br><span class="line"><span class="deletion">-w        显示加宽可以显示较多的资讯</span></span><br><span class="line"><span class="deletion">-au       显示较详细的资讯</span></span><br><span class="line"><span class="deletion">-aux      显示所有包含其他使用者的行程</span></span><br></pre></td></tr></table></figure>

<ul>
<li><code>ps -ef</code> 各项指标解释</li>
</ul>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># ps -ef</span></span><br><span class="line">UID         PID   PPID  C STIME TTY          TIME CMD</span><br><span class="line">root          <span class="number">1</span>      <span class="number">0</span>  <span class="number">6</span> <span class="number">18</span>:<span class="number">39</span> pts<span class="regexp">/0    00:02:27 java -jar /</span>opt/lp-admin.jar</span><br><span class="line">root        <span class="number">102</span>      <span class="number">0</span>  <span class="number">0</span> <span class="number">18</span>:<span class="number">40</span> pts<span class="regexp">/1    00:00:00 /</span>bin/bash</span><br><span class="line">root        <span class="number">158</span>    <span class="number">102</span>  <span class="number">0</span> <span class="number">18</span>:<span class="number">47</span> pts<span class="regexp">/1    00:00:00 /u</span>sr<span class="regexp">/bin/</span>python <span class="regexp">/usr/</span>bin/dstat</span><br><span class="line">---------各项指标解析-----------------------</span><br><span class="line">UID    程序的执行者 UID</span><br><span class="line">PID    进程的ID号</span><br><span class="line">PPID   则是其上级父程序的ID</span><br><span class="line">C      cpu 使用的资源百分比</span><br><span class="line">TTY    登入者的终端机位置</span><br><span class="line">TIME   CPU 执行的时间</span><br><span class="line">CMD    进程执行的命令</span><br></pre></td></tr></table></figure>

<ul>
<li><code>ps -aux</code> 各项指标解释</li>
</ul>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># ps -aux</span></span><br><span class="line">ps -aux</span><br><span class="line">USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND</span><br><span class="line">root          <span class="number">1</span>  <span class="number">7.0</span>  <span class="number">5.3</span> <span class="number">13278220</span> <span class="number">1736948</span> pts<span class="regexp">/0 Ssl+ 18:39   2:24 java -jar /</span>opt/lp-admin.jar</span><br><span class="line">root        <span class="number">102</span>  <span class="number">0.0</span>  <span class="number">0.0</span>  <span class="number">15264</span>  <span class="number">2044</span> pts<span class="regexp">/1    Ss   18:40   0:00 /</span>bin/bash</span><br><span class="line">root        <span class="number">158</span>  <span class="number">0.0</span>  <span class="number">0.0</span>  <span class="number">52176</span>  <span class="number">6756</span> pts<span class="regexp">/1    T    18:47   0:00 /u</span>sr<span class="regexp">/bin/</span>python <span class="regexp">/usr/</span>bin/dstat</span><br><span class="line">root        <span class="number">159</span>  <span class="number">0.0</span>  <span class="number">0.0</span>  <span class="number">52176</span>  <span class="number">6756</span> pts<span class="regexp">/1    T    18:49   0:00 /u</span>sr<span class="regexp">/bin/</span>python <span class="regexp">/usr/</span>bin/dstat -n -N eth0,total</span><br><span class="line">---------各项指标解析-----------------------</span><br><span class="line">USER    行程拥有者</span><br><span class="line">PID     pid</span><br><span class="line">%CPU    占用的 CPU 使用率</span><br><span class="line">%MEM    占用的记忆体使用率</span><br><span class="line">VSZ     占用的虚拟记忆体大小</span><br><span class="line">RSS     占用的记忆体大小</span><br><span class="line">TTY     终端的次要装置号码 (minor device number of tty)</span><br><span class="line">STAT    该进程程的状态:</span><br><span class="line">   D:  无法中断的休眠状态 (通常 IO 的进程)</span><br><span class="line">   R:  正在执行中</span><br><span class="line">   S:  可中断的睡眠状态</span><br><span class="line">   T:  暂停状态或跟踪状态</span><br><span class="line">   Z:  僵尸进程（zombie），无法正常终止</span><br><span class="line">   X： 退出状态，进程即将被销毁</span><br><span class="line">START   登入者的终端机位置</span><br><span class="line">TIME    CPU 执行的时间</span><br><span class="line">COMMAND 进程执行的命令</span><br></pre></td></tr></table></figure>

<h3 id="lsof"><a href="#lsof" class="headerlink" title="lsof"></a>lsof</h3><ul>
<li>lsof（List Open Files） 用于查看你进程开打的文件，打开文件的进程，进程打开的端口(TCP、UDP)。命令格式 <code>lsof ［options］ filename</code></li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">options 参数解释</span><br><span class="line"></span><br><span class="line"><span class="deletion">-a            列出打开文件存在的进程</span></span><br><span class="line"><span class="deletion">-c&lt;进程名&gt;     列出指定进程所打开的文件(常用)</span></span><br><span class="line"><span class="deletion">-p&lt;进程号&gt;     列出指定进程号所打开的文件(常用)</span></span><br><span class="line"><span class="deletion">-g            列出属于gid的进程详情</span></span><br><span class="line"><span class="deletion">-u&lt;uname/uid&gt; 显示归属uname或uid的进程情况</span></span><br><span class="line"><span class="deletion">-d&lt;fd文件号&gt;   列出占用该文件号的进程</span></span><br><span class="line"><span class="addition">+d&lt;目录&gt;       列出目录下被打开的文件</span></span><br><span class="line"><span class="addition">+D&lt;目录&gt;       递归列出目录下被打开的文件</span></span><br><span class="line"><span class="deletion">-n&lt;目录&gt;       列出使用NFS的文件</span></span><br><span class="line"><span class="deletion">-i&lt;条件&gt;       列出符合条件的进程。（ip4/ip6协议、端口、 @ip ）</span></span><br><span class="line"><span class="deletion">-u            列出UID号进程详情</span></span><br></pre></td></tr></table></figure>

<ul>
<li>lsof 各项指标解释</li>
</ul>
<figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># lsof</span></span><br><span class="line">command  PID <span class="keyword">USER</span>   <span class="title">FD</span>   <span class="keyword">type</span>   DEVICE     SIZE     <span class="keyword">NODE</span>  <span class="title">NAME</span></span><br><span class="line">init       <span class="number">1</span> root  txt   REG       <span class="number">8</span>,<span class="number">2</span>    <span class="number">43496</span>  <span class="number">6121706</span> /sbin/init</span><br><span class="line"></span><br><span class="line">---------各项指标解析-----------------------</span><br><span class="line">COMMAND  进程的名称 </span><br><span class="line">PID      进程标识符 </span><br><span class="line"><span class="keyword">USER</span>     <span class="title">进程所有者 </span></span><br><span class="line"><span class="title">FD</span>       文件描述符，应用程序通过文件描述符识别该文件。如cwd、txt等 </span><br><span class="line"><span class="keyword">TYPE</span>     文件类型，如DIR、REG等 </span><br><span class="line">DEVICE   指定磁盘的名称 </span><br><span class="line">SIZE     文件的大小 </span><br><span class="line"><span class="keyword">NODE</span>     <span class="title">索引节点（文件在磁盘上的标识） </span></span><br><span class="line"><span class="title">NAME</span>     打开文件的确切名称</span><br></pre></td></tr></table></figure>

<ul>
<li>lsof 示例</li>
</ul>
<figure class="highlight vala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">~~ 显示所有打开<span class="number">80</span>端口的进程</span><br><span class="line"><span class="meta"># lsof -i:80       </span></span><br><span class="line">~~ 那个进程在占用/etc/passwd</span><br><span class="line"><span class="meta"># lsof /etc/passwd </span></span><br><span class="line">~~ 显示使用fd为<span class="number">1211</span>的进程</span><br><span class="line"><span class="meta"># lsof -d 1211     </span></span><br><span class="line">~~ 显示那些文件被pid为 <span class="number">1211</span> 的进程打开</span><br><span class="line"><span class="meta"># lsof -p 1211     </span></span><br><span class="line">~~ 查看sendmail进程的文件使用情况</span><br><span class="line"><span class="meta"># lsof -c sendmail </span></span><br></pre></td></tr></table></figure>

<h3 id="pidof"><a href="#pidof" class="headerlink" title="pidof"></a>pidof</h3><ul>
<li>pidof 是linux系统中用来查找正在运行进程的进程号(pid)的工具。如果我们提前知道进程名，则可以根据进程名查找pid，命令格式：<code>pidof [options] 进程名称</code></li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">options 选项参数</span><br><span class="line"></span><br><span class="line"><span class="deletion">-s： 仅返回一个进程号；</span></span><br><span class="line"><span class="deletion">-c： 仅显示具有相同“root”目录的进程</span></span><br><span class="line"><span class="deletion">-x： 显示由脚本开启的进程</span></span><br><span class="line"><span class="deletion">-o： 指定不显示的进程ID</span></span><br></pre></td></tr></table></figure>

<ul>
<li>pidof 示例</li>
</ul>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># pidof -s nginx</span></span><br><span class="line"><span class="number">1211</span></span><br></pre></td></tr></table></figure>

<h3 id="top"><a href="#top" class="headerlink" title="top"></a>top</h3><ul>
<li>top 命令是用来监控Linux系统状况，比如cpu、内存，进程等资源使用情况。命令格式：<code>top [-options]</code></li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">options 选项参数</span><br><span class="line"></span><br><span class="line"><span class="deletion">-i&lt;时间&gt;    设置刷新间隔时间</span></span><br><span class="line"><span class="deletion">-u&lt;用户名&gt;    指定用户名</span></span><br><span class="line"><span class="deletion">-p&lt;进程号&gt;    指定进程</span></span><br><span class="line"><span class="deletion">-H           开启线程查看</span></span><br></pre></td></tr></table></figure>

<ul>
<li>top 各项输出指标解释</li>
</ul>
<figure class="highlight tap"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># top</span></span><br><span class="line">top - 18:20:27 up<span class="number"> 26 </span>days,  8:30, <span class="number"> 2 </span>users,  load average: 0.04, 0.09, 0.13</span><br><span class="line">Tasks:<span class="number"> 168 </span>total,  <span class="number"> 1 </span>running,<span class="number"> 167 </span>sleeping,  <span class="number"> 0 </span>stopped,  <span class="number"> 0 </span>zombie</span><br><span class="line">%Cpu(s):  0.3 us,  0.5 sy,  0.0 ni, 99.1 id,  0.0 wa,  0.0 hi,  0.1 si,  0.0 st</span><br><span class="line">KiB Mem: <span class="number"> 32762356 </span>total,<span class="number"> 14675196 </span>used,<span class="number"> 18087160 </span>free,     <span class="number"> 884 </span>buffers</span><br><span class="line">KiB Swap: <span class="number"> 2103292 </span>total,       <span class="number"> 0 </span>used, <span class="number"> 2103292 </span>free. <span class="number"> 6580028 </span>cached Mem</span><br><span class="line"></span><br><span class="line">PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                </span><br><span class="line">1260 root     <span class="number"> 20 </span> <span class="number"> 0 </span>7933492 1.173g <span class="number"> 14004 </span>S 0.333 3.753  58:20.74 java                       </span><br><span class="line">1503 root     <span class="number"> 20 </span> <span class="number"> 0 </span> <span class="number"> 69172 </span> <span class="number"> 2240 </span> <span class="number"> 1412 </span>S 0.333 0.007   0:48.05 httpd                       </span><br><span class="line">1520 daemon   <span class="number"> 20 </span> <span class="number"> 0 </span><span class="number"> 358140 </span> <span class="number"> 3980 </span>  <span class="number"> 776 </span>S 0.333 0.012   6:19.55 httpd                       </span><br><span class="line">2323 mysql    <span class="number"> 20 </span> <span class="number"> 0 </span>19.918g 4.538g  <span class="number"> 9404 </span>S 0.333 14.52 352:51.44 mysqld                     </span><br><span class="line">.......</span><br><span class="line">---------各项指标解析------------------------------------------------<span class="yaml"><span class="meta">---</span></span></span><br><span class="line"><span class="yaml"><span class="string">第一行统计信息区</span></span></span><br><span class="line"><span class="yaml">    <span class="number">18</span><span class="string">:20:27</span>                     <span class="string">当前时间</span></span></span><br><span class="line"><span class="yaml">    <span class="string">up</span> <span class="number">25</span> <span class="string">days,</span> <span class="number">17</span><span class="string">:29</span>             <span class="string">系统运行时间，格式为时:分</span></span></span><br><span class="line"><span class="yaml">    <span class="number">1</span> <span class="string">user</span>                     <span class="string">当前登录用户数</span></span></span><br><span class="line"><span class="yaml">    <span class="attr">load average:</span> <span class="number">0.04</span><span class="string">,</span> <span class="number">0.09</span><span class="string">,</span> <span class="number">0.13</span>  <span class="string">系统负载，三个数值分别为</span> <span class="number">1</span><span class="string">分钟、5分钟、15分钟前到现在的平均值</span></span></span><br><span class="line"><span class="yaml"></span></span><br><span class="line"><span class="yaml"><span class="string">Tasks：进程相关信息</span></span></span><br><span class="line"><span class="yaml">    <span class="string">running</span>   <span class="string">正在运行的进程数</span></span></span><br><span class="line"><span class="yaml">    <span class="string">sleeping</span>  <span class="string">睡眠的进程数</span></span></span><br><span class="line"><span class="yaml">    <span class="string">stopped</span>   <span class="string">停止的进程数</span></span></span><br><span class="line"><span class="yaml">    <span class="string">zombie</span>    <span class="string">僵尸进程数</span></span></span><br><span class="line"><span class="yaml"><span class="string">Cpu(s)：CPU相关信息</span></span></span><br><span class="line"><span class="yaml">    <span class="string">%us：表示用户空间程序的cpu使用率（没有通过nice调度）</span></span></span><br><span class="line"><span class="yaml">    <span class="string">%sy：表示系统空间的cpu使用率，主要是内核程序</span></span></span><br><span class="line"><span class="yaml">    <span class="string">%ni：表示用户空间且通过nice调度过的程序的cpu使用率</span></span></span><br><span class="line"><span class="yaml">    <span class="string">%id：空闲cpu</span></span></span><br><span class="line"><span class="yaml">    <span class="string">%wa：cpu运行时在等待io的时间</span></span></span><br><span class="line"><span class="yaml">    <span class="string">%hi：cpu处理硬中断的数量</span></span></span><br><span class="line"><span class="yaml">    <span class="string">%si：cpu处理软中断的数量</span></span></span><br><span class="line"><span class="yaml">    <span class="string">%st：被虚拟机偷走的cpu</span></span></span><br><span class="line"><span class="yaml"><span class="string">Mem</span>  <span class="string">内存信息</span>  </span></span><br><span class="line"><span class="yaml">    <span class="string">total</span> <span class="string">物理内存总量</span></span></span><br><span class="line"><span class="yaml">    <span class="string">used</span> <span class="string">使用的物理内存总量</span></span></span><br><span class="line"><span class="yaml">    <span class="string">free</span> <span class="string">空闲内存总量</span></span></span><br><span class="line"><span class="yaml">    <span class="string">buffers</span> <span class="string">用作内核缓存的内存量</span></span></span><br><span class="line"><span class="yaml"><span class="string">Swap</span> <span class="string">内存信息</span>  </span></span><br><span class="line"><span class="yaml">    <span class="string">total</span> <span class="string">交换区总量</span></span></span><br><span class="line"><span class="yaml">    <span class="string">used</span> <span class="string">使用的交换区总量</span></span></span><br><span class="line"><span class="yaml">    <span class="string">free</span> <span class="string">空闲交换区总量</span></span></span><br><span class="line"><span class="yaml">    <span class="string">cached</span> <span class="string">缓冲的交换区总量</span></span></span><br><span class="line"><span class="yaml"></span></span><br><span class="line"><span class="yaml"><span class="string">~~</span> <span class="string">常用的指标</span></span></span><br><span class="line"><span class="yaml"><span class="string">PID</span> <span class="string">进程id</span></span></span><br><span class="line"><span class="yaml"><span class="string">PPID</span> <span class="string">父进程id</span></span></span><br><span class="line"><span class="yaml"><span class="string">UID</span> <span class="string">进程所有者的用户id</span></span></span><br><span class="line"><span class="yaml"><span class="string">USER</span> <span class="string">进程所有者的用户名</span></span></span><br><span class="line"><span class="yaml"><span class="string">GROUP</span> <span class="string">进程所有者的组名</span></span></span><br><span class="line"><span class="yaml"><span class="string">TTY</span> <span class="string">启动进程的终端名。不是从终端启动的进程则显示为</span> <span class="string">?</span></span></span><br><span class="line"><span class="yaml"><span class="string">PR</span> <span class="string">优先级</span></span></span><br><span class="line"><span class="yaml"><span class="string">NI</span> <span class="string">nice值。负值表示高优先级，正值表示低优先级</span></span></span><br><span class="line"><span class="yaml"><span class="string">P</span> <span class="string">最后使用的CPU，仅在多CPU环境下有意义</span></span></span><br><span class="line"><span class="yaml"><span class="string">%CPU</span> <span class="string">上次更新到现在的CPU时间占用百分比</span></span></span><br><span class="line"><span class="yaml"><span class="string">TIME</span> <span class="string">进程使用的CPU时间总计，单位秒</span></span></span><br><span class="line"><span class="yaml"><span class="string">TIME+</span> <span class="string">进程使用的CPU时间总计，单位1/100秒</span></span></span><br><span class="line"><span class="yaml"><span class="string">%MEM</span> <span class="string">进程使用的物理内存百分比</span></span></span><br><span class="line"><span class="yaml"><span class="string">VIRT</span> <span class="string">进程使用的虚拟内存总量，单位kb。VIRT=SWAP+RES</span></span></span><br><span class="line"><span class="yaml"><span class="string">SWAP</span> <span class="string">进程使用的虚拟内存中，被换出的大小，单位kb。</span></span></span><br><span class="line"><span class="yaml"><span class="string">RES</span> <span class="string">进程使用的、未被换出的物理内存大小，单位kb。RES=CODE+DATA</span></span></span><br><span class="line"><span class="yaml"><span class="string">CODE</span> <span class="string">可执行代码占用的物理内存大小，单位kb</span></span></span><br><span class="line"><span class="yaml"><span class="string">DATA</span> <span class="string">可执行代码以外的部分(数据段+栈)占用的物理内存大小，单位kb</span></span></span><br><span class="line"><span class="yaml"><span class="string">SHR</span> <span class="string">共享内存大小，单位kb</span></span></span><br><span class="line"><span class="yaml"><span class="string">S</span>       <span class="string">进程状态;</span> <span class="string">相关枚举值解释查看</span> <span class="string">ps</span> <span class="string">-ef</span> <span class="string">S</span> <span class="string">项解释</span></span></span><br><span class="line"><span class="yaml"><span class="string">COMMAND</span> <span class="string">进程启动执行的命令行</span>    </span></span><br></pre></td></tr></table></figure>

<ul>
<li>top 命令下，查看信息常用快捷键</li>
</ul>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">h    显示快捷键帮助</span><br><span class="line">k    终止一个进程</span><br><span class="line"><span class="selector-tag">i</span>    开/关忽略闲置和僵死进程</span><br><span class="line"><span class="selector-tag">q</span>    退出程序</span><br><span class="line">r    重新安排一个进程的优先级别</span><br><span class="line">S     切换到累计模式</span><br><span class="line">s    更改刷新间隔时间，单位秒</span><br><span class="line">f,F    从当前显示中添加或者删除项目</span><br><span class="line">o,O    改变显示项目的顺序</span><br><span class="line">l    切换显示平均负载和启动时间信息</span><br><span class="line">m     切换显示内存信息</span><br><span class="line">t    切换显示进程和CPU状态信息</span><br><span class="line">c    切换显示命令名称和完整命令行</span><br><span class="line">M     根据内存使用大小排序</span><br><span class="line"><span class="selector-tag">P</span>    根据CPU使用率进行排序 （默认排序）</span><br><span class="line">T    根据时间/累计时间进行排序</span><br><span class="line"><span class="number">1</span>    展开多核cpu显示</span><br><span class="line">H       线程查看模式切换为开或关</span><br></pre></td></tr></table></figure>

<h3 id="free"><a href="#free" class="headerlink" title="free"></a>free</h3><ul>
<li>free 可查看系统内存的使用情况，包括物理内存、交换内存(swap)和内核缓冲区内存。命令格式：<code>free [-bkmg][-hlot][s delay][-c count]</code></li>
</ul>
<figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">free 选项参数</span><br><span class="line"></span><br><span class="line"> -b,-k,-m,-g  表示输出显示的单位为 bytes,KB,MB,<span class="keyword">or</span> GB，不添加选项的话默认以 KB 为单位显示</span><br><span class="line"> -h          以人类可读的方式显示，即后边会自动带上单位</span><br><span class="line"> -l          显示详细的低内存和高内存统计信息（增加了 Low 和 High 这两行显示）</span><br><span class="line"> -o          使用旧的格式显示（不显示 -/+buffers/cache 这一行）</span><br><span class="line"> -t          增加显示 Total 行，Total = Mem + Swap</span><br><span class="line"> -s delay    每 delay 秒重复打印一次，delay 为具体的秒数</span><br><span class="line"> -c count    循环打印 count 次后退出，count 为具体的次数。需要配合 -s delay 使用</span><br><span class="line"><span class="meta"># free -m</span></span><br><span class="line">             total       used       free     shared    buffers     cached</span><br><span class="line">Mem:         <span class="number">32107</span>      <span class="number">30414</span>       <span class="number">1692</span>          <span class="number">0</span>       <span class="number">1962</span>       <span class="number">8489</span></span><br><span class="line">-/+ buffers/cache:      <span class="number">19962</span>      <span class="number">12144</span></span><br><span class="line">Swap:            <span class="number">0</span>          <span class="number">0</span>          <span class="number">0</span></span><br><span class="line">------各项指标解释-------------------------------------------------</span><br><span class="line">Mem 表示物理内存统计：</span><br><span class="line"> total   物理内存总量，total = used + free</span><br><span class="line"> used    总使用缓存的数量（包含 buffers 与 cache），但其中可能部分缓存并未实际使用</span><br><span class="line"> free    未被分配的内存</span><br><span class="line"> shared  共享内存，一般系统不会用到，总是<span class="number">0</span></span><br><span class="line"> buffers  系统分配但未被使用的 buffers 数量</span><br><span class="line"> cached  系统分配但未被使用的 cache 数量</span><br><span class="line"> </span><br><span class="line">-/+ buffers/cache：</span><br><span class="line"> used    实际使用内存，等于第一行的 used - buffers - cached</span><br><span class="line"> free    实际可用内存，等于第一行的 free + buffers + cached</span><br><span class="line"></span><br><span class="line">Swap表示交换区的使用情况，也就是我们通常所说的虚拟内存</span><br><span class="line"> total   总量虚拟内存</span><br><span class="line"> used    使用的虚拟内存</span><br><span class="line"> free    空闲的虚拟内存</span><br></pre></td></tr></table></figure>

<h3 id="mpstat"><a href="#mpstat" class="headerlink" title="mpstat"></a>mpstat</h3><ul>
<li>mpstat 是 Multiprocessor Statistics 的缩写，可以查看多核心的 cpu 中每个计算核心的统计数据。命令格式：<code>mpstat [-P &#123;cpu|ALL&#125;] [delay [count]]</code></li>
</ul>
<figure class="highlight mel"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">-P &#123;cpu|ALL&#125;  表示监控哪个CPU， cpu在[<span class="number">0</span>,cpu个数<span class="number">-1</span>]中取值</span><br><span class="line">delay          相邻的两次采样的间隔时间</span><br><span class="line">count          采样的次数，count只能和delay一起使用</span><br><span class="line"># mpstat  -P ALL <span class="number">2</span></span><br><span class="line">Linux <span class="number">3.10</span><span class="number">.0</span><span class="number">-862.</span>el7.x86_64 (<span class="number">8</span>f57ec39327b)      <span class="number">07</span>/<span class="number">11</span>/<span class="number">2021</span>      _x86_64_        (<span class="number">6</span> CPU)</span><br><span class="line"></span><br><span class="line"><span class="number">07</span>:<span class="number">19</span>:<span class="number">07</span> PM  CPU    %usr   %nice    %sys %iowait    %irq   %soft  %steal  %guest  %gnice   %idle</span><br><span class="line"><span class="number">07</span>:<span class="number">19</span>:<span class="number">09</span> PM  all   <span class="number">21.43</span>    <span class="number">3.36</span>    <span class="number">6.54</span>    <span class="number">6.45</span>    <span class="number">0.00</span>    <span class="number">1.29</span>    <span class="number">0.00</span>    <span class="number">0.00</span>    <span class="number">0.00</span>   <span class="number">60.93</span></span><br><span class="line"><span class="number">07</span>:<span class="number">19</span>:<span class="number">09</span> PM    <span class="number">0</span>   <span class="number">20.41</span>    <span class="number">3.57</span>    <span class="number">7.14</span>    <span class="number">4.08</span>    <span class="number">0.00</span>    <span class="number">1.53</span>    <span class="number">0.00</span>    <span class="number">0.00</span>    <span class="number">0.00</span>   <span class="number">63.27</span></span><br><span class="line"><span class="number">07</span>:<span class="number">19</span>:<span class="number">09</span> PM    <span class="number">1</span>   <span class="number">22.45</span>    <span class="number">3.06</span>    <span class="number">6.12</span>    <span class="number">5.10</span>    <span class="number">0.00</span>    <span class="number">1.53</span>    <span class="number">0.00</span>    <span class="number">0.00</span>    <span class="number">0.00</span>   <span class="number">61.73</span></span><br><span class="line">---------各项输出指标解释----------------------------------------------</span><br><span class="line">CPU 处理器ID </span><br><span class="line">%usr 在 delay 时间段里，用户态的 cpu 时间（%）</span><br><span class="line">%nice </span><br><span class="line">%sys 在 delay 时间段里，核心时间（%） </span><br><span class="line">%iowait 在 delay 时间段里，硬盘IO等待时间（%） </span><br><span class="line">%irq 在 delay 时间段里，硬中断时间（%） </span><br><span class="line">%soft 在 delay 时间段里，软中断时间（%） </span><br><span class="line">%steal 虚拟机管理器在服务另一个虚拟处理器时虚拟CPU处在非自愿等待下花费时间的百分比 </span><br><span class="line">%guest 显示运行虚拟处理器时 CPU 花费时间的百分比 </span><br><span class="line">%gnice  gnice/total*<span class="number">100</span></span><br><span class="line">%idle 在internal时间段里，CPU除去等待磁盘IO操作外的因为任何原因而空闲的时间闲置时间（%）</span><br></pre></td></tr></table></figure>

<h3 id="iostat"><a href="#iostat" class="headerlink" title="iostat"></a>iostat</h3><ul>
<li>iostat 主要用于输出 CPU 和磁盘 I/O 相关的统计信息,命令格式: <code>iostat [options] [delay [count]]</code></li>
</ul>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">options</span> 选项参数</span><br><span class="line"></span><br><span class="line">-c      只显示系统CPU统计信息，即单独输出avg-cpu结果，不包括device结果</span><br><span class="line">-d      单独输出Device结果，不包括cpu结果</span><br><span class="line">-k<span class="regexp">/-m   输出结果以kB/m</span>B为单位，而不是以扇区数为单位</span><br><span class="line">-x      输出更详细的io设备统计信息</span><br><span class="line">delay   每次输出间隔时间</span><br><span class="line"><span class="keyword">count</span>   表示输出次数，不带<span class="keyword">count</span>表示循环输出</span><br></pre></td></tr></table></figure>

<ul>
<li>默认命令<code>iostat</code>的各项指标解析</li>
</ul>
<figure class="highlight x86asm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"># iostat</span><br><span class="line">Linux <span class="number">4.4</span><span class="number">.73</span>-<span class="number">5</span>-<span class="meta">default</span>        <span class="number">2021</span>年<span class="number">07</span>月<span class="number">08</span>日  _x86_64_        (<span class="number">40</span> <span class="meta">CPU</span>)</span><br><span class="line"></span><br><span class="line">avg-<span class="meta">cpu</span>:  %user   %nice %system %iowait  %steal   %idle</span><br><span class="line">           <span class="number">2.50</span>    <span class="number">0.41</span>    <span class="number">0.94</span>    <span class="number">0.02</span>    <span class="number">0.00</span>   <span class="number">96.13</span></span><br><span class="line"><span class="symbol"></span></span><br><span class="line"><span class="symbol">Device:</span>            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn</span><br><span class="line">sda              <span class="number">12.09</span>        <span class="number">27.80</span>       <span class="number">507.24</span>   <span class="number">57343492</span> <span class="number">1046298308</span></span><br><span class="line">sdb              <span class="number">17.95</span>        <span class="number">30.91</span>       <span class="number">647.84</span>   <span class="number">63751096</span> <span class="number">1336305974</span></span><br><span class="line">------各项指标解析-----------------------------------------------------------</span><br><span class="line">avg-<span class="meta">cpu</span>: 总体<span class="meta">cpu</span>使用情况统计信息，对于多核<span class="meta">cpu</span>，这里为所有<span class="meta">cpu</span>的平均值</span><br><span class="line">    %user      用户空间的<span class="meta">CPU</span>使用率</span><br><span class="line">    %nice      <span class="meta">CPU</span>处在带NICE值的用户模式下的时间百分比</span><br><span class="line">    %system    内核空间的<span class="meta">CPU</span>使用率</span><br><span class="line">    %iowait    <span class="meta">CPU</span>等待IO的百分比 </span><br><span class="line">    %steal     虚拟机的虚拟机<span class="meta">CPU</span>使用的<span class="meta">CPU</span></span><br><span class="line">    %idle      空闲的<span class="meta">CPU</span>   </span><br><span class="line"><span class="symbol"></span></span><br><span class="line"><span class="symbol">Device:</span> 各磁盘设备的IO统计信息。各列含义如下：</span><br><span class="line">    tps        每秒进程下发的IO读、写请求数量</span><br><span class="line">    KB_read/s  每秒从驱动器读入的数据量，单位为K。</span><br><span class="line">    KB_wrtn/s  每秒从驱动器写入的数据量，单位为K。</span><br><span class="line">    KB_read    读入数据总量，单位为K。</span><br><span class="line">    KB_wrtn    写入数据总量，单位为K</span><br></pre></td></tr></table></figure>

<ul>
<li><code>iostat -x -k -d 1 2</code>的各项指标解析</li>
</ul>
<figure class="highlight makefile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># iostat -x -k -d 1 1</span></span><br><span class="line">Linux 4.4.73-5-default (ceshi44)        2021年07月08日  _x86_64_        (40 CPU)</span><br><span class="line"></span><br><span class="line"><span class="section">Device:  rrqm/s   wrqm/s  r/s    w/s    rkB/s   wkB/s  avgrq-sz avgqu-sz await r_await w_await  svctm  %util</span></span><br><span class="line">sda      0.08     2.48    0.37   11.71  27.80   507.24  88.53   0.02     1.34   14.96    0.90   0.09   0.10</span><br><span class="line">sdb      0.00     1.20    1.28   16.67  30.91   647.83  75.61   0.17     9.51    9.40    9.52   0.32   0.57</span><br><span class="line">------各项指标解析----------------------------------------------------------</span><br><span class="line"><span class="section">rrqm/s:   每秒对该设备的读请求被合并次数，文件系统会对读取同块(block)的请求进行合并</span></span><br><span class="line"><span class="section">wrqm/s:   每秒对该设备的写请求被合并次数</span></span><br><span class="line"><span class="section">r/s:      每秒完成的读次数</span></span><br><span class="line"><span class="section">w/s:      每秒完成的写次数</span></span><br><span class="line"><span class="section">rkB/s:    每秒读数据量(kB为单位)</span></span><br><span class="line"><span class="section">wkB/s:    每秒写数据量(kB为单位)</span></span><br><span class="line"><span class="section">avgrq-sz: 平均每次IO操作的数据量(扇区数为单位)</span></span><br><span class="line"><span class="section">avgqu-sz: 平均等待处理的IO请求队列长度</span></span><br><span class="line"><span class="section">await:    平均每次IO请求等待时间(包括等待时间和处理时间，毫秒为单位)</span></span><br><span class="line"><span class="section">svctm:    平均每次IO请求的处理时间(毫秒为单位)</span></span><br><span class="line"><span class="section">%util:    采用周期内用于IO操作的时间比率，即IO队列非空的时间比率</span></span><br></pre></td></tr></table></figure>

<h3 id="netstat"><a href="#netstat" class="headerlink" title="netstat"></a>netstat</h3><ul>
<li>netstat 命令用于显示各种网络相关信息，如网络连接，路由表，网络连接状态。命令格式：<code>netstat [-options]</code></li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">options 参数解析</span><br><span class="line"></span><br><span class="line"><span class="deletion">-a (all)显示所有选项，默认不显示 Listen 相关</span></span><br><span class="line"><span class="deletion">-t (tcp)仅显示tcp相关选项</span></span><br><span class="line"><span class="deletion">-u (udp)仅显示udp相关选项</span></span><br><span class="line"><span class="deletion">-n 拒绝显示别名，能显示数字的全部转化成数字。</span></span><br><span class="line"><span class="deletion">-l 仅列出有在 Listen (监听) 的服務状态</span></span><br><span class="line"></span><br><span class="line"><span class="deletion">-p 显示建立相关链接的程序名</span></span><br><span class="line"><span class="deletion">-r 显示路由信息，路由表</span></span><br><span class="line"><span class="deletion">-e 显示扩展信息，例如uid等</span></span><br><span class="line"><span class="deletion">-s 按各个协议进行统计</span></span><br><span class="line"><span class="deletion">-c 每隔一个固定时间，执行该netstat命令</span></span><br></pre></td></tr></table></figure>

<ul>
<li>各项输出指标解析</li>
</ul>
<figure class="highlight delphi"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"># netstat -pt </span><br><span class="line">Proto Recv-Q Send-Q <span class="keyword">Local</span> Address   Foreign Address  State   PID/<span class="keyword">Program</span> <span class="keyword">name</span>  </span><br><span class="line">tcp        <span class="number">0</span>      <span class="number">0</span> localhost:<span class="number">30037</span> *:*              LISTEN  <span class="number">2109</span>/firefox</span><br><span class="line">....</span><br><span class="line">------各项指标解析----------------------------------------</span><br><span class="line">Proto           协议</span><br><span class="line">Recv-Q          接收队列 ，一般都应该是<span class="number">0</span>。如果不是则表示软件包正在队列中堆积</span><br><span class="line">Send-Q          发送队列，一般都应该是<span class="number">0</span>。如果不是则表示软件包正在队列中堆积</span><br><span class="line"><span class="keyword">Local</span> Address   本地地址+port</span><br><span class="line">Foreign Address 远端地址+port</span><br><span class="line">State           状态</span><br><span class="line">PID             进程pid</span><br><span class="line"><span class="keyword">Program</span> <span class="keyword">name</span>    进程名</span><br></pre></td></tr></table></figure>

<ul>
<li>netstat 常用命令示例</li>
</ul>
<figure class="highlight vala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"># netstat -anp</span></span><br><span class="line"><span class="meta"># netstat -tnlp</span></span><br></pre></td></tr></table></figure>

<h3 id="vmstat"><a href="#vmstat" class="headerlink" title="vmstat"></a>vmstat</h3><ul>
<li>vmstat (虚拟内存统计)可对操作系统的内存、进程、CPU，磁盘进行监控。相比top，可以看到整个机器的CPU、内存、IO的使用情况，而不是单单看到各个进程的CPU使用率和内存使用率(使用场景不一样)</li>
<li>命令格式</li>
</ul>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="regexp">//</span> -a：显示活跃和非活跃内存 -n：只在开始时显示一次各字段名称</span><br><span class="line"><span class="comment"># vmstat [-a] [-n] [delay [count]]</span></span><br><span class="line"><span class="regexp">//</span> f:总的fork进程 s：内存使用的详细信息 d：磁盘的读/写 m：系统的slab信息</span><br><span class="line"><span class="comment"># vmstat [-fsdm] </span></span><br><span class="line"><span class="regexp">//</span> 查看指定磁盘分区统计信息</span><br><span class="line"><span class="comment"># vmstat [-p disk partition]</span></span><br></pre></td></tr></table></figure>

<ul>
<li>vmstat 示例</li>
</ul>
<figure class="highlight dts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">$ vmstat <span class="number">2</span> <span class="number">1</span></span><br><span class="line">procs --------memory---------   --swap-- --io--- -system-- ----cpu-----</span><br><span class="line">r b   swpd free    buff  cache    si so   bi  bo  in   cs  us sy id wa st</span><br><span class="line"><span class="number">1</span> <span class="number">0</span>      <span class="number">0</span> <span class="number">3498472</span> <span class="number">315836</span> <span class="number">3819540</span>  <span class="number">0</span>  <span class="number">0</span>    <span class="number">0</span>   <span class="number">1</span>   <span class="number">2</span>    <span class="number">0</span>  <span class="number">3</span>  <span class="number">1</span>  <span class="number">96</span>  <span class="number">0</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line">------各项指标解析----------------------------------------</span><br><span class="line">Procs（进程）</span><br><span class="line"><span class="symbol">  r:</span>     运行队列中进程数量，当这个值超过了CPU数目，就会出现CPU瓶颈了</span><br><span class="line">  b：    等待IO的进程数量</span><br><span class="line"></span><br><span class="line">Memory（内存）：</span><br><span class="line"><span class="symbol">  swpd:</span>  使用虚拟内存大小，如果大于<span class="number">0</span>，表示你的机器物理内存不足了，如果不是程序内存泄露的原因，那么你该升级内存了</span><br><span class="line"><span class="symbol">  free:</span>  可用内存大小</span><br><span class="line"><span class="symbol">  buff:</span>  用作缓冲的内存大小</span><br><span class="line"><span class="symbol">  cache:</span> 用作缓存的内存大</span><br><span class="line">  </span><br><span class="line">Swap：</span><br><span class="line"><span class="symbol">  si:</span>    每秒从交换区写到内存的大小，如果这个值大于<span class="number">0</span>，表示物理内存不够用或者内存泄露了，要查找耗内存进程解决掉</span><br><span class="line"><span class="symbol">  so:</span>    每秒写入交换区的内存大小</span><br><span class="line"></span><br><span class="line">IO：（现在的Linux版本块的大小为<span class="number">1024</span>bytes）</span><br><span class="line"><span class="symbol">  bi:</span>    每秒读取的块数</span><br><span class="line"><span class="symbol">  bo:</span>    每秒写入的块数，bi和bo一般都要接近<span class="number">0</span>，不然就是IO过于频繁，需要调整</span><br><span class="line"></span><br><span class="line">系统</span><br><span class="line"><span class="symbol">  in:</span>    每秒中断数，包括时钟中断</span><br><span class="line"><span class="symbol">  cs:</span>    每秒上下文切换数，调用系统函数，就要进行上下文切换，线程的切换，也要进程上下文切换，这个值要越小越好</span><br><span class="line"></span><br><span class="line">CPU（以百分比表示）：</span><br><span class="line"><span class="symbol">  us:</span>    用户进程执行时间 </span><br><span class="line"><span class="symbol">  sy:</span>    系统进程执行时间 </span><br><span class="line"><span class="symbol">  id:</span>    空闲时间(包括IO等待时间)，中央处理器的空闲时间</span><br><span class="line"><span class="symbol">  wa:</span>    等待 IO 时间  </span><br><span class="line"><span class="symbol">  st:</span>    虚拟机的虚拟机CPU使用的CPU</span><br></pre></td></tr></table></figure>

<h3 id="dstat"><a href="#dstat" class="headerlink" title="dstat"></a>dstat</h3><ul>
<li>vmstat 是对系统的整体情况进行统计，无法对某个进程进行深入分析，所以推荐下 dstat。dstat 是一个可以取代vmstat、iostat、netstat 这些命令的多功能命令工具，执行 dstat 命令，默认情况它会收集-cpu-、-disk-、-net-、－paging-、-system-的数据，一秒钟收集一次。命令格式：<code>dstat [options] [delay [count]]</code>，其中使用 -p pid 选项可针对某一进程进行统计监控</li>
</ul>
<figure class="highlight haml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">options 常用参数解析</span><br><span class="line"></span><br><span class="line">-<span class="ruby">l         显示负载统计量</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">c         开启cpu统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">C &lt;CPU&gt;   选项跟着 cpu 的编号，显示该cpu 的统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">d         开启 disk 统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">g         开启分页统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">y         开启系统统计，包括中断和上下文切换</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">i         开启中断统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">s     开启 swap 统计，包括used, free</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">m         显示内存使用率（包括used，buffer，cache，free值）</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">n         开启网络读写统计</span></span><br><span class="line"><span class="ruby"></span>–socket    显示网络统计数据</span><br><span class="line">–tcp       显示常用的TCP统计</span><br><span class="line">-<span class="ruby">N    选项跟着网络设备名，多个用逗号隔开，进行网络统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">p         开启对进程统计，runnable, uninterruptible, new</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">r         io开启请求统计，包括read requests, write requests</span></span><br><span class="line"><span class="ruby"></span></span><br><span class="line">-<span class="ruby">-output文件  此选项也比较有用，可以把状态信息以csv的格式重定向到指定的文件中</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">–disk-util   显示某一时间磁盘的忙碌状况</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">–freespace   显示当前磁盘空间使用率</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">–<span class="built_in">proc</span>-count  显示正在运行的程序数量</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">-top-bio-adv 指出块I/O最大的进程</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">-top-cputime 耗费CPU时间最多的进程名和耗费时间</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">-top-cpu-adv 显示CPU占用最大的进程</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">–top-io      显示正常I/O最大的进程</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">–top-mem     显示占用最多内存的进程</span></span><br></pre></td></tr></table></figure>

<ul>
<li>输出指标解析</li>
</ul>
<figure class="highlight tap"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># dstat</span></span><br><span class="line">You did not select any stats, using -cdngy by default.</span><br><span class="line">----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--</span><br><span class="line">usr sys idl wai hiq siq| read  writ| recv  send|  in   out | int   csw </span><br><span class="line"><span class="number"> 29 </span> <span class="number"> 7 </span><span class="number"> 57 </span> <span class="number"> 6 </span> <span class="number"> 0 </span>  1|  85k 1457k|  <span class="number"> 0 </span>   <span class="number"> 0 </span>|  <span class="number"> 0 </span>   <span class="number"> 0 </span>|8350    67k</span><br><span class="line"><span class="number"> 30 </span> <span class="number"> 9 </span><span class="number"> 54 </span> <span class="number"> 6 </span> <span class="number"> 0 </span>  1|  <span class="number"> 0 </span> 1290k| 857B  568B|  <span class="number"> 0 </span>   <span class="number"> 0 </span>|  33k   75k</span><br><span class="line">...</span><br><span class="line"></span><br><span class="line">------各项指标解析--------------------------------<span class="yaml"><span class="meta">---</span></span></span><br><span class="line"><span class="yaml"><span class="string">CPU的使用率</span></span></span><br><span class="line"><span class="yaml">  <span class="string">usr</span>   <span class="string">显示了用户占比</span></span></span><br><span class="line"><span class="yaml">  <span class="string">sys</span>   <span class="string">系统占比</span></span></span><br><span class="line"><span class="yaml">  <span class="string">idl</span>   <span class="string">空闲占比</span></span></span><br><span class="line"><span class="yaml">  <span class="string">wai</span>   <span class="string">等待占比</span></span></span><br><span class="line"><span class="yaml">  <span class="string">hiq</span>   <span class="string">硬中断</span></span></span><br><span class="line"><span class="yaml">  <span class="string">siq</span>   <span class="string">软中断情况</span></span></span><br><span class="line"><span class="yaml"></span></span><br><span class="line"><span class="yaml"><span class="string">磁盘的读写</span></span></span><br><span class="line"><span class="yaml">  <span class="string">read</span>  <span class="string">磁盘的读总数</span></span></span><br><span class="line"><span class="yaml">  <span class="string">writ</span>  <span class="string">磁盘的写总数</span></span></span><br><span class="line"><span class="yaml"> </span></span><br><span class="line"><span class="yaml"><span class="string">网络设备发送和接受的数据</span></span></span><br><span class="line"><span class="yaml">  <span class="string">recv</span>  <span class="string">网络收数据总数</span></span></span><br><span class="line"><span class="yaml">  <span class="string">send</span>  <span class="string">网络发数据总数</span></span></span><br><span class="line"><span class="yaml"></span></span><br><span class="line"><span class="yaml"><span class="string">系统的分页活动</span></span></span><br><span class="line"><span class="yaml">  <span class="string">in</span>    <span class="string">内存页换入</span></span></span><br><span class="line"><span class="yaml">  <span class="string">out</span>   <span class="string">内存页换出</span></span></span><br><span class="line"><span class="yaml">  </span></span><br><span class="line"><span class="yaml"><span class="string">系统统计</span>  </span></span><br><span class="line"><span class="yaml">  <span class="string">int</span>   <span class="string">统计中断</span></span></span><br><span class="line"><span class="yaml">  <span class="string">csw</span>   <span class="string">上下文切换</span></span></span><br></pre></td></tr></table></figure>

<ul>
<li>指定展示各个网卡的收发状态</li>
</ul>
<figure class="highlight perl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># dstat -n -N eth0,total</span></span><br><span class="line">--net/eth<span class="number">0</span>---net/total-</span><br><span class="line"> <span class="keyword">recv</span>  <span class="keyword">send</span>: <span class="keyword">recv</span>  <span class="keyword">send</span></span><br><span class="line">   <span class="number">0</span>     <span class="number">0</span> :   <span class="number">0</span>     <span class="number">0</span> </span><br><span class="line"> <span class="number">140</span>B  <span class="number">140</span>B: <span class="number">140</span>B  <span class="number">140</span>B</span><br><span class="line">  <span class="number">18</span>k <span class="number">6570</span>B:  <span class="number">18</span>k <span class="number">6570</span>B</span><br></pre></td></tr></table></figure>

<ul>
<li>查看全部内存都有谁在占用</li>
</ul>
<figure class="highlight coq"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># dstat -g -l -m -s --<span class="built_in">top</span>-mem</span><br><span class="line">---paging-- ---load-avg--- ------memory-usage----- ----<span class="built_in">swap</span>--- --most-expensive-</span><br><span class="line">  <span class="built_in">in</span>   out | <span class="type">1m</span>   <span class="number">5</span>m  <span class="number">15</span>m | <span class="type">used</span>  buff  cach  free| <span class="type">used</span>  free|  <span class="type">memory</span> process </span><br><span class="line">   <span class="number">0</span>     <span class="number">0</span> |<span class="type">5</span><span class="number">.44</span> <span class="number">4.77</span> <span class="number">5.09</span>|<span class="type">23</span><span class="number">.2</span>G <span class="number">2108</span>k <span class="number">7892</span>M  <span class="number">233</span>M|   <span class="type">0</span>     <span class="number">0</span> |<span class="type">java</span>        <span class="number">1670</span>M</span><br><span class="line">   <span class="number">0</span>     <span class="number">0</span> |<span class="type">5</span><span class="number">.44</span> <span class="number">4.77</span> <span class="number">5.09</span>|<span class="type">23</span><span class="number">.3</span>G <span class="number">2108</span>k <span class="number">7893</span>M  <span class="number">221</span>M|   <span class="type">0</span>     <span class="number">0</span> |<span class="type">java</span>        <span class="number">1670</span></span><br></pre></td></tr></table></figure>

<ul>
<li>进程最耗资源统计</li>
</ul>
<figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"># dstat --top-cpu-adv 1 2</span></span><br><span class="line">-------most-expensive-cpu-process-------</span><br><span class="line">process              pid  cpu read write</span><br><span class="line">java                   <span class="number">1</span>  <span class="number">0.0</span>%  <span class="number">43B</span>   <span class="number">0</span>                </span><br><span class="line">java                   <span class="number">1</span>  <span class="number">0.2</span>%   <span class="number">0</span>    <span class="number">0</span></span><br></pre></td></tr></table></figure>

<h3 id="sar"><a href="#sar" class="headerlink" title="sar"></a>sar</h3><ul>
<li>sar 和 dstat 差不多，随你们各自喜好使用，可以从多方面对系统的资源进行监控，包括：文件的读写情况、系统调用的使用情况、磁盘I/O、CPU效率、内存使用状况、进程活动及 IPC 有关的活动等。命令格式：<code>sar [options] [-A] [-o file] delay [count]</code>。delay 为采样间隔，count 为采样次数，默认值是1</li>
</ul>
<figure class="highlight erlang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">options 选项参数</span><br><span class="line"></span><br><span class="line">-A          所有报告的总和</span><br><span class="line">-o file     表示将命令结果以二进制格式存放在文件中，file 是文件名</span><br><span class="line">-u          输出CPU使用情况的统计信息</span><br><span class="line">-v          输出inode、文件和其他内核表的统计信息</span><br><span class="line">-d          输出每一个块设备的活动信息</span><br><span class="line">-b          显示I/O和传送速率的统计信息（相对-d 是汇总信息）</span><br><span class="line">-r          输出内存和交换空间的统计信息</span><br><span class="line">-R          输出内存页面的统计信息</span><br><span class="line">-a          文件读写情况</span><br><span class="line">-q          队列长度和平均负载</span><br><span class="line">-c          输出进程统计信息，每秒创建的进程数</span><br><span class="line">-y          终端设备活动情况</span><br><span class="line">-w          输出系统交换活动信息</span><br><span class="line">-x &lt;pid&gt;    显示给定进程的统计信息</span><br><span class="line">-n &lt;关键词&gt;  统计网络信息</span><br><span class="line">    关键词可以是：</span><br><span class="line">        DEV    网卡</span><br><span class="line">        EDEV   网卡 <span class="params">(错误)</span></span><br><span class="line">        NFS    NFS 客户端</span><br><span class="line">        NFSD   NFS 服务器</span><br><span class="line">        SOCK   Sockets <span class="params">(套接字)</span>    <span class="params">(v4)</span></span><br><span class="line">        SOCK6  Sockets <span class="params">(套接字)</span>    <span class="params">(v6)</span></span><br><span class="line">        IP     IP 流    <span class="params">(v4)</span></span><br><span class="line">        EIP    IP 流    <span class="params">(v4)</span> <span class="params">(失败信息)</span></span><br><span class="line">        ICMP   ICMP 流  <span class="params">(v4)</span></span><br><span class="line">        EICMP  ICMP 流  <span class="params">(v4)</span> <span class="params">(失败信息)</span></span><br><span class="line">        TCP    TCP 流   <span class="params">(v4)</span></span><br><span class="line">        ETCP   TCP 流   <span class="params">(v4)</span> <span class="params">(失败信息)</span></span><br><span class="line">        UDP    UDP 流   <span class="params">(v4)</span></span><br><span class="line">        IP6    IP 流    <span class="params">(v6)</span></span><br><span class="line">        EIP6   IP 流    <span class="params">(v6)</span> <span class="params">(失败信息)</span></span><br><span class="line">        ICMP6  ICMP 流  <span class="params">(v6)</span></span><br><span class="line">        EICMP6 ICMP 流  <span class="params">(v6)</span> <span class="params">(失败信息)</span></span><br><span class="line">        UDP6   UDP 流   <span class="params">(v6)</span></span><br></pre></td></tr></table></figure>

<ul>
<li>查看 CPU 使用情况：<code>sar -u 1 2</code></li>
</ul>
<figure class="highlight haml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"># sar -u  1 2</span><br><span class="line">Linux 3.10.0-862.el7.x86_64 (8f57ec39327b)      07/11/2021      _x86_64_        (6 CPU)</span><br><span class="line"></span><br><span class="line">07:02:04 PM     CPU     %user     %nice   %system   %iowait    %steal     %idle</span><br><span class="line">07:02:05 PM     all     23.90      3.22      7.97      5.25      0.00     59.66</span><br><span class="line">07:02:06 PM     all     26.53      4.76      8.84      5.95      0.00     53.91</span><br><span class="line">Average:        all     25.21      3.99      8.40      5.60      0.00     56.79</span><br><span class="line">-<span class="ruby">-----各项指标解析---------------------------------</span></span><br><span class="line"><span class="ruby"></span><span class="tag">%<span class="selector-tag">user</span></span>     用户空间的CPU使用</span><br><span class="line"><span class="tag">%<span class="selector-tag">nice</span></span>     改变过优先级的进程的CPU使用率</span><br><span class="line"><span class="tag">%<span class="selector-tag">system</span></span>   内核空间的CPU使用率</span><br><span class="line"><span class="tag">%<span class="selector-tag">iowait</span></span>   CPU等待IO的百分比 </span><br><span class="line"><span class="tag">%<span class="selector-tag">steal</span></span>    虚拟机的虚拟机CPU使用的CPU</span><br><span class="line"><span class="tag">%<span class="selector-tag">idle</span></span>     空闲的CPU</span><br></pre></td></tr></table></figure>

<ul>
<li>查看内存使用情况  <code>sar -r</code></li>
</ul>
<figure class="highlight tap"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># sar -r 1 2</span></span><br><span class="line">Linux 3.10.0-862.el7.x86_64 (8f57ec39327b)      07/11/2021      _x86_64_        (6 CPU)</span><br><span class="line"></span><br><span class="line">07:05:16 PM kbmemfree kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty</span><br><span class="line">07:05:17 PM   <span class="number"> 299596 </span><span class="number"> 32398396 </span>    99.08     <span class="number"> 2084 </span> <span class="number"> 7615088 </span><span class="number"> 37900868 </span>   115.91 <span class="number"> 27267692 </span> <span class="number"> 3809860 </span>      672</span><br><span class="line">07:05:18 PM   <span class="number"> 298932 </span><span class="number"> 32399060 </span>    99.09     <span class="number"> 2084 </span> <span class="number"> 7615848 </span><span class="number"> 37900100 </span>   115.91 <span class="number"> 27267828 </span> <span class="number"> 3810252 </span>      488</span><br><span class="line">Average:      <span class="number"> 299264 </span><span class="number"> 32398728 </span>    99.08     <span class="number"> 2084 </span> <span class="number"> 7615468 </span><span class="number"> 37900484 </span>   115.91 <span class="number"> 27267760 </span> <span class="number"> 3810056 </span>      580</span><br><span class="line"></span><br><span class="line">------各项指标解析-----------------<span class="yaml"><span class="meta">---</span></span></span><br><span class="line"><span class="yaml"><span class="string">kbmemfree</span>   <span class="string">空闲的物理内存大小</span></span></span><br><span class="line"><span class="yaml"><span class="string">kbmemused</span>   <span class="string">使用中的物理内存大小</span></span></span><br><span class="line"><span class="yaml"><span class="string">%memused</span>    <span class="string">物理内存使用率</span></span></span><br><span class="line"><span class="yaml"><span class="string">kbbuffers</span>   <span class="string">内核中作为缓冲区使用的物理内存大小，kbbuffers和kbcached:这两个值就是free命令中的buffer和cache.</span> </span></span><br><span class="line"><span class="yaml"><span class="string">kbcached</span>    <span class="string">缓存的文件大小</span></span></span><br><span class="line"><span class="yaml"><span class="string">kbcommit</span>    <span class="string">保证当前系统正常运行所需要的最小内存，即为了确保内存不溢出而需要的最少内存（物理内存+Swap分区）</span></span></span><br><span class="line"><span class="yaml"><span class="string">commit</span>      <span class="string">这个值是kbcommit与内存总量（物理内存+swap分区）的一个百分比的值</span></span></span><br></pre></td></tr></table></figure>

<ul>
<li>查看 IO 和传递速率：<code>sar -b</code></li>
</ul>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># sar -b 1 2</span></span><br><span class="line">Linux <span class="number">3.10</span>.<span class="number">0</span>-<span class="number">862</span>.el7.x86_64 (<span class="number">8</span>f57ec39327b)      <span class="number">07</span><span class="regexp">/11/</span><span class="number">2021</span>      _x86_64_        (<span class="number">6</span> CPU)</span><br><span class="line"></span><br><span class="line"><span class="number">07</span>:<span class="number">06</span>:<span class="number">08</span> PM       tps      rtps      wtps   bread<span class="regexp">/s   bwrtn/</span>s</span><br><span class="line"><span class="number">07</span>:<span class="number">06</span>:<span class="number">09</span> PM    <span class="number">171.00</span>      <span class="number">0.00</span>    <span class="number">171.00</span>      <span class="number">0.00</span>   <span class="number">3431.00</span></span><br><span class="line"><span class="number">07</span>:<span class="number">06</span>:<span class="number">10</span> PM    <span class="number">163.00</span>      <span class="number">0.00</span>    <span class="number">163.00</span>      <span class="number">0.00</span>   <span class="number">2620.00</span></span><br><span class="line">Average:       <span class="number">167.00</span>      <span class="number">0.00</span>    <span class="number">167.00</span>      <span class="number">0.00</span>   <span class="number">3025.50</span></span><br><span class="line">------各项指标解析--------------------</span><br><span class="line">tps      磁盘每秒钟的IO总数，等于iostat中的tps</span><br><span class="line">rtps     每秒钟从磁盘读取的IO总数</span><br><span class="line">wtps     每秒钟从写入到磁盘的IO总数</span><br><span class="line">bread/s  每秒钟从磁盘读取的块总数</span><br><span class="line">bwrtn/s  每秒钟此写入到磁盘的块总数</span><br></pre></td></tr></table></figure>

<ul>
<li>网络接口信息：<code>sar -n DEV</code></li>
</ul>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># sar -n DEV 1 1</span></span><br><span class="line">Linux <span class="number">3.10</span>.<span class="number">0</span>-<span class="number">862</span>.el7.x86_64 (<span class="number">8</span>f57ec39327b)      <span class="number">07</span><span class="regexp">/11/</span><span class="number">2021</span>      _x86_64_        (<span class="number">6</span> CPU)</span><br><span class="line"></span><br><span class="line"><span class="number">07</span>:<span class="number">06</span>:<span class="number">57</span> PM     IFACE   rxpck<span class="regexp">/s   txpck/</span>s    rxkB<span class="regexp">/s    txkB/</span>s   rxcmp<span class="regexp">/s   txcmp/</span>s  rxmcst/s</span><br><span class="line"><span class="number">07</span>:<span class="number">06</span>:<span class="number">58</span> PM      eth0      <span class="number">2.00</span>      <span class="number">4.00</span>      <span class="number">1.45</span>      <span class="number">0.56</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span></span><br><span class="line"><span class="number">07</span>:<span class="number">06</span>:<span class="number">58</span> PM        lo      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span></span><br><span class="line"><span class="number">07</span>:<span class="number">06</span>:<span class="number">58</span> PM     tunl0      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span></span><br><span class="line"></span><br><span class="line">Average:        IFACE   rxpck<span class="regexp">/s   txpck/</span>s    rxkB<span class="regexp">/s    txkB/</span>s   rxcmp<span class="regexp">/s   txcmp/</span>s  rxmcst/s</span><br><span class="line">Average:         eth0      <span class="number">2.00</span>      <span class="number">4.00</span>      <span class="number">1.45</span>      <span class="number">0.56</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span></span><br><span class="line">Average:           lo      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span></span><br><span class="line">Average:        tunl0      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span></span><br><span class="line">------各项指标解析--------------------</span><br><span class="line">IFACE    本地网卡接口的名称</span><br><span class="line">rxpck/s  每秒钟接受的数据包</span><br><span class="line">txpck/s  每秒钟发送的数据库</span><br><span class="line">rxKB/S   每秒钟接受的数据包大小，单位为KB</span><br><span class="line">txKB/S   每秒钟发送的数据包大小，单位为KB</span><br><span class="line">rxcmp/s  每秒钟接受的压缩数据包</span><br><span class="line">txcmp/s  每秒钟发送的压缩包</span><br><span class="line">rxmcst/s 每秒钟接收的多播数据包  </span><br></pre></td></tr></table></figure>

<ul>
<li>查看磁盘使用情况：<code>sar -d</code>。相对 -b 它可以看到各个设备的信息，-b 输出的是汇总信息</li>
</ul>
<figure class="highlight mathematica"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">sar</span> <span class="operator">-</span><span class="variable">d</span> <span class="operator">-</span><span class="variable">p</span> <span class="number">1</span> <span class="number">1</span>  </span><br><span class="line"><span class="variable">Linux</span> <span class="number">3.10</span><span class="number">.0</span><span class="operator">-</span><span class="number">862.</span><span class="variable">el7</span><span class="operator">.</span><span class="type">x86_</span><span class="number">64</span> <span class="punctuation">(</span><span class="number">8</span><span class="variable">f57ec39327b</span><span class="punctuation">)</span>      <span class="number">07</span><span class="operator">/</span><span class="number">11</span><span class="operator">/</span><span class="number">2021</span>      <span class="type">_x86</span><span class="type">_</span><span class="number">64</span><span class="type">_</span>        <span class="punctuation">(</span><span class="number">6</span> <span class="variable">CPU</span><span class="punctuation">)</span></span><br><span class="line"></span><br><span class="line"><span class="number">07</span><span class="operator">:</span><span class="number">08</span><span class="operator">:</span><span class="number">41</span> <span class="variable">PM</span>       <span class="variable">DEV</span>       <span class="variable">tps</span>  <span class="type">rd_sec</span><span class="operator">/</span><span class="variable">s</span>  <span class="type">wr_sec</span><span class="operator">/</span><span class="variable">s</span>  <span class="variable">avgrq</span><span class="operator">-</span><span class="variable">sz</span>  <span class="variable">avgqu</span><span class="operator">-</span><span class="variable">sz</span>     <span class="variable">await</span>     <span class="variable">svctm</span>     <span class="operator">%</span><span class="variable">util</span></span><br><span class="line"><span class="number">07</span><span class="operator">:</span><span class="number">08</span><span class="operator">:</span><span class="number">42</span> <span class="variable">PM</span>       <span class="variable">sdb</span>    <span class="number">160.00</span>      <span class="number">0.00</span>   <span class="number">2914.00</span>     <span class="number">18.21</span>      <span class="number">1.51</span>      <span class="number">9.43</span>      <span class="number">3.73</span>     <span class="number">59.70</span></span><br><span class="line"><span class="number">07</span><span class="operator">:</span><span class="number">08</span><span class="operator">:</span><span class="number">42</span> <span class="variable">PM</span>       <span class="variable">sdc</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span></span><br><span class="line"><span class="number">07</span><span class="operator">:</span><span class="number">08</span><span class="operator">:</span><span class="number">42</span> <span class="variable">PM</span>       <span class="variable">sda</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span></span><br><span class="line"></span><br><span class="line"><span class="variable">Average</span><span class="operator">:</span>          <span class="variable">DEV</span>       <span class="variable">tps</span>  <span class="type">rd_sec</span><span class="operator">/</span><span class="variable">s</span>  <span class="type">wr_sec</span><span class="operator">/</span><span class="variable">s</span>  <span class="variable">avgrq</span><span class="operator">-</span><span class="variable">sz</span>  <span class="variable">avgqu</span><span class="operator">-</span><span class="variable">sz</span>     <span class="variable">await</span>     <span class="variable">svctm</span>     <span class="operator">%</span><span class="variable">util</span></span><br><span class="line"><span class="variable">Average</span><span class="operator">:</span>          <span class="variable">sdb</span>    <span class="number">160.00</span>      <span class="number">0.00</span>   <span class="number">2914.00</span>     <span class="number">18.21</span>      <span class="number">1.51</span>      <span class="number">9.43</span>      <span class="number">3.73</span>     <span class="number">59.70</span></span><br><span class="line"><span class="variable">Average</span><span class="operator">:</span>          <span class="variable">sdc</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span></span><br><span class="line"><span class="variable">Average</span><span class="operator">:</span>          <span class="variable">sda</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span>      <span class="number">0.00</span></span><br><span class="line"><span class="operator">------</span>各项指标解析<span class="operator">--------------------</span></span><br><span class="line"><span class="variable">DEV</span>       磁盘设备的名称，如果不加<span class="operator">-</span><span class="variable">p</span>，会显示<span class="variable">dev253</span><span class="operator">-</span><span class="number">0</span>类似的设备名称，因此加上<span class="operator">-</span><span class="variable">p</span>显示的名称更直接</span><br><span class="line"><span class="variable">tps</span>       每秒<span class="built_in">I</span><span class="operator">/</span><span class="built_in">O</span>的传输总数</span><br><span class="line"><span class="type">rd_sec</span><span class="operator">/</span><span class="variable">s</span>  每秒读取的扇区的总数</span><br><span class="line"><span class="type">wr_sec</span><span class="operator">/</span><span class="variable">s</span>  每秒写入的扇区的总数</span><br><span class="line"><span class="variable">avgrq</span><span class="operator">-</span><span class="variable">sz</span>  平均每次次磁盘<span class="built_in">I</span><span class="operator">/</span><span class="built_in">O</span>操作的数据大小（扇区）</span><br><span class="line"><span class="variable">avgqu</span><span class="operator">-</span><span class="variable">sz</span>  磁盘请求队列的平均长度</span><br><span class="line"><span class="variable">await</span>     从请求磁盘操作到系统调用完成处理，每次请求的平均消耗时间</span><br><span class="line"><span class="variable">svctm</span>     <span class="built_in">I</span><span class="operator">/</span><span class="built_in">O</span>的服务处理时间，即不包括请求队列中的时间</span><br><span class="line"><span class="operator">%</span><span class="variable">util</span>     <span class="built_in">I</span><span class="operator">/</span><span class="built_in">O</span>请求占用的<span class="variable">CPU</span>百分比，值越高，说明<span class="built_in">I</span><span class="operator">/</span><span class="built_in">O</span>越慢</span><br></pre></td></tr></table></figure>

<ul>
<li>统计socket连接信息：<code>sar -n SOCK 1 1</code></li>
</ul>
<figure class="highlight tap"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># sar -n SOCK 1 1</span></span><br><span class="line">Linux 3.10.0-862.el7.x86_64 (8f57ec39327b)      07/11/2021      _x86_64_        (6 CPU)</span><br><span class="line"></span><br><span class="line">07:09:18 PM    totsck    tcpsck    udpsck    rawsck   ip-frag    tcp-tw</span><br><span class="line">07:09:19 PM    <span class="number"> 10910 </span>     <span class="number"> 261 </span>       <span class="number"> 0 </span>       <span class="number"> 0 </span>       <span class="number"> 0 </span>      562</span><br><span class="line">Average:       <span class="number"> 10910 </span>     <span class="number"> 261 </span>       <span class="number"> 0 </span>       <span class="number"> 0 </span>       <span class="number"> 0 </span>      562</span><br><span class="line">------各项指标解析-----------------<span class="yaml"><span class="meta">---</span></span></span><br><span class="line"><span class="yaml"><span class="string">totsck</span>   <span class="string">当前被使用的socket总数</span></span></span><br><span class="line"><span class="yaml"><span class="string">tcpsck</span>   <span class="string">当前正在被使用的TCP的socket总数</span></span></span><br><span class="line"><span class="yaml"><span class="string">udpsck</span>   <span class="string">当前正在被使用的UDP的socket总数</span></span></span><br><span class="line"><span class="yaml"><span class="string">rawsck</span>   <span class="string">当前正在被使用于RAW的skcket总数</span></span></span><br><span class="line"><span class="yaml"><span class="string">if-frag</span>  <span class="string">当前的IP分片的数目</span></span></span><br><span class="line"><span class="yaml"><span class="string">tcp-tw</span>   <span class="string">TCP套接字中处于TIME-WAIT状态的连接数量</span></span></span><br></pre></td></tr></table></figure>

<ul>
<li>TCP连接的统计：<code>sar -n TCP</code></li>
</ul>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># sar -n TCP 1 1</span></span><br><span class="line">Linux <span class="number">3.10</span>.<span class="number">0</span>-<span class="number">862</span>.el7.x86_64 (<span class="number">8</span>f57ec39327b)      <span class="number">07</span><span class="regexp">/11/</span><span class="number">2021</span>      _x86_64_        (<span class="number">6</span> CPU)</span><br><span class="line"></span><br><span class="line"><span class="number">07</span>:<span class="number">09</span>:<span class="number">39</span> PM  active<span class="regexp">/s passive/</span>s    iseg<span class="regexp">/s    oseg/</span>s</span><br><span class="line"><span class="number">07</span>:<span class="number">09</span>:<span class="number">40</span> PM      <span class="number">1.00</span>      <span class="number">0.00</span>      <span class="number">5.00</span>      <span class="number">7.00</span></span><br><span class="line">Average:         <span class="number">1.00</span>      <span class="number">0.00</span>      <span class="number">5.00</span>      <span class="number">7.00</span></span><br><span class="line">------各项指标解析--------------------</span><br><span class="line">active/s   新的主动连接</span><br><span class="line">passive/s  新的被动连接</span><br><span class="line">iseg/s     接受的段</span><br><span class="line">oseg/s     输出的段</span><br></pre></td></tr></table></figure>

<h3 id="pidstat"><a href="#pidstat" class="headerlink" title="pidstat"></a>pidstat</h3><ul>
<li>pidstat是sysstat工具的一个命令，用于监控全部或指定进程的cpu、内存、线程、设备IO等系统资源的占用情况。命令格式：<code>pidstat [options] [delay [count]]</code></li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">options 参数解析</span><br><span class="line"></span><br><span class="line"><span class="deletion">-u         默认的参数，显示各个进程的cpu使用统计</span></span><br><span class="line"><span class="deletion">-r         显示各个进程的内存使用统计</span></span><br><span class="line"><span class="deletion">-d         显示各个进程的IO使用情况</span></span><br><span class="line"><span class="deletion">-p &lt;pid&gt;   指定进程号</span></span><br><span class="line"><span class="deletion">-w         显示每个进程的上下文切换情况</span></span><br><span class="line"><span class="deletion">-t         显示选择进程的线程的统计信息</span></span><br></pre></td></tr></table></figure>

<ul>
<li>查看所有进程的 CPU 使用情况：<code>pidstat -u</code></li>
</ul>
<figure class="highlight haml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"># pidstat -u</span><br><span class="line">Linux 4.4.73-5-default (ceshi44)        2021年07月08日  _x86_64_        (40 CPU)</span><br><span class="line"></span><br><span class="line">14时11分56秒   UID  PID  %usr %system  %guest    %CPU   CPU  Command</span><br><span class="line">14时11分56秒     0    1  0.15    0.06    0.00    0.22    22  systemd</span><br><span class="line">....</span><br><span class="line">-<span class="ruby">-----各项指标解析----------------------------------------</span></span><br><span class="line"><span class="ruby"></span>UID      进程所属UID</span><br><span class="line">PID      进程ID</span><br><span class="line"><span class="tag">%<span class="selector-tag">usr</span></span>     进程在用户空间占用cpu的百分比</span><br><span class="line"><span class="tag">%<span class="selector-tag">system</span></span>  进程在内核空间占用cpu的百分比</span><br><span class="line"><span class="tag">%<span class="selector-tag">guest</span></span>   进程在虚拟机占用cpu的百分比</span><br><span class="line"><span class="tag">%<span class="selector-tag">CPU</span></span>     进程占用cpu的百分比</span><br><span class="line">CPU      处理进程的cpu编号</span><br><span class="line">Command  当前进程对应的命令</span><br></pre></td></tr></table></figure>

<ul>
<li>内存使用情况统计：<code>pidstat -r</code></li>
</ul>
<figure class="highlight tap"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># pidstat -r</span></span><br><span class="line">Linux 4.4.73-5-default (ceshi44)        2021年07月08日  _x86_64_        (40 CPU)</span><br><span class="line"></span><br><span class="line">14时13分08秒   UID       PID  minflt/s  majflt/s     VSZ    RSS   %MEM  Command</span><br><span class="line">14时13分08秒    <span class="number"> 0 </span>       <span class="number"> 1 </span>    41.04      0.00 <span class="number"> 186020 </span> <span class="number"> 5968 </span>  0.00  systemd</span><br><span class="line">14时13分08秒    <span class="number"> 0 </span>     <span class="number"> 443 </span>     0.00      0.00   <span class="number"> 5828 </span> <span class="number"> 3004 </span>  0.00  pidstat</span><br><span class="line">....</span><br><span class="line">------各项指标解析-------------------------------------<span class="yaml"><span class="meta">---</span></span></span><br><span class="line"><span class="yaml"><span class="string">PID</span>       <span class="string">进程标识符</span></span></span><br><span class="line"><span class="yaml"><span class="string">Minflt/s</span>  <span class="string">任务每秒发生的次要错误，不需要从磁盘中加载页</span></span></span><br><span class="line"><span class="yaml"><span class="string">Majflt/s</span>  <span class="string">任务每秒发生的主要错误，需要从磁盘中加载页</span></span></span><br><span class="line"><span class="yaml"><span class="string">VSZ</span>       <span class="string">虚拟地址大小，虚拟内存的使用KB</span></span></span><br><span class="line"><span class="yaml"><span class="string">RSS</span>       <span class="string">常驻集合大小，非交换区五里内存使用KB</span></span></span><br><span class="line"><span class="yaml"><span class="string">Command</span>   <span class="string">task命令名</span></span></span><br></pre></td></tr></table></figure>

<ul>
<li>显示各个进程的IO使用情况：<code>pidstat -d</code></li>
</ul>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># pidstat -d</span></span><br><span class="line">Linux <span class="number">3.10</span>.<span class="number">0</span>-<span class="number">862</span>.el7.x86_64 (<span class="number">8</span>f57ec39327b)      <span class="number">07</span><span class="regexp">/11/</span><span class="number">2021</span>      _x86_64_        (<span class="number">6</span> CPU)</span><br><span class="line"></span><br><span class="line"><span class="number">06</span>:<span class="number">42</span>:<span class="number">35</span> PM   UID       PID   kB_rd<span class="regexp">/s   kB_wr/</span>s kB_ccwr/s  Command</span><br><span class="line"><span class="number">06</span>:<span class="number">42</span>:<span class="number">35</span> PM     <span class="number">0</span>         <span class="number">1</span>      <span class="number">0.05</span>      <span class="number">0.00</span>      <span class="number">0.00</span>  java</span><br><span class="line"><span class="number">06</span>:<span class="number">42</span>:<span class="number">35</span> PM     <span class="number">0</span>       <span class="number">102</span>      <span class="number">0.04</span>      <span class="number">0.05</span>      <span class="number">0.00</span>  bash</span><br><span class="line">------各项指标解析---------------------------</span><br><span class="line">kB_rd/s   每秒从磁盘读取的KB</span><br><span class="line">kB_wr/s   每秒写入磁盘KB</span><br><span class="line">kB_ccwr/s 任务取消的写入磁盘的KB。当任务截断脏的pagecache的时候会发生</span><br><span class="line">Command   进程执行命令</span><br></pre></td></tr></table></figure>

<ul>
<li>显示每个进程的上下文切换情况：<code>pidstat -w</code></li>
</ul>
<figure class="highlight tap"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># pidstat -w</span></span><br><span class="line">Linux 3.10.0-862.el7.x86_64 (8f57ec39327b)      07/11/2021      _x86_64_        (6 CPU)</span><br><span class="line"></span><br><span class="line">06:43:23 PM   UID       PID   cswch/s nvcswch/s  Command</span><br><span class="line">06:43:23 PM    <span class="number"> 0 </span>       <span class="number"> 1 </span>     0.00      0.00  java</span><br><span class="line">06:43:23 PM    <span class="number"> 0 </span>     <span class="number"> 102 </span>     0.00      0.00  bash</span><br><span class="line">06:43:23 PM    <span class="number"> 0 </span>     <span class="number"> 150 </span>     0.00      0.00  pidstat</span><br><span class="line">------各项指标解析------------------------<span class="yaml"><span class="meta">---</span></span></span><br><span class="line"><span class="yaml"><span class="string">PID</span>       <span class="string">进程id</span></span></span><br><span class="line"><span class="yaml"><span class="string">Cswch/s</span>   <span class="string">每秒主动任务上下文切换数量</span></span></span><br><span class="line"><span class="yaml"><span class="string">Nvcswch/s</span> <span class="string">每秒被动任务上下文切换数量</span></span></span><br><span class="line"><span class="yaml"><span class="string">Command</span>   <span class="string">进程执行命令</span></span></span><br></pre></td></tr></table></figure>

<ul>
<li>指定进程并（ -t）显示进程的线程统计信息：<code>pidstat -t -p 1211</code></li>
</ul>
<figure class="highlight tap"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># pidstat -t -p 1211</span></span><br><span class="line">06:44:37 PM   UID      TGID       TID    %usr %system  %guest    %CPU   CPU  Command</span><br><span class="line">06:44:37 PM    <span class="number"> 0 </span>       <span class="number"> 1 </span>        -    0.00    0.00    0.00    0.00    <span class="number"> 3 </span> java</span><br><span class="line">06:44:37 PM    <span class="number"> 0 </span>        -        <span class="number"> 1 </span>   0.00    0.00    0.00    0.00    <span class="number"> 3 </span> |__java</span><br><span class="line">06:44:37 PM    <span class="number"> 0 </span>        -        <span class="number"> 6 </span>   0.00    0.00    0.00    0.00    <span class="number"> 5 </span> |__java</span><br><span class="line">06:44:37 PM    <span class="number"> 0 </span>        -        <span class="number"> 7 </span>   0.00    0.00    0.00    0.00    <span class="number"> 4 </span> |__java</span><br><span class="line">...</span><br><span class="line">------各项指标解析------------------------<span class="yaml"><span class="meta">---</span></span></span><br><span class="line"><span class="yaml"><span class="string">TGID</span>      <span class="string">主线程的表示</span></span></span><br><span class="line"><span class="yaml"><span class="string">TID</span>       <span class="string">线程id</span></span></span><br><span class="line"><span class="yaml"><span class="string">%usr</span>      <span class="string">进程在用户空间占用cpu的百分比</span></span></span><br><span class="line"><span class="yaml"><span class="string">%system</span>   <span class="string">进程在内核空间占用cpu的百分比</span></span></span><br><span class="line"><span class="yaml"><span class="string">%guest</span>    <span class="string">进程在虚拟机占用cpu的百分比</span></span></span><br><span class="line"><span class="yaml"><span class="string">%CPU</span>      <span class="string">进程占用cpu的百分比</span></span></span><br><span class="line"><span class="yaml"><span class="string">CPU</span>       <span class="string">处理进程的cpu编号</span></span></span><br><span class="line"><span class="yaml"><span class="string">Command</span>   <span class="string">当前进程对应的命令</span></span></span><br></pre></td></tr></table></figure>

<h3 id="pstree"><a href="#pstree" class="headerlink" title="pstree"></a>pstree</h3><ul>
<li>ps 命令可以显示当前正在运行的那些进程的信息，但是对于它们之间的关系却显示得不够清晰，pstree 命令可以以树状图显示进程间的关系。命令格式：<code>pstree [-p] &lt;pid&gt;</code></li>
</ul>
<figure class="highlight erlang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"># pstree -p <span class="number">3169</span></span><br><span class="line"><span class="function"><span class="title">mongod</span><span class="params">(<span class="number">3169</span>)</span>─┬─&#123;<span class="title">mongod</span>&#125;<span class="params">(<span class="number">3170</span>)</span></span></span><br><span class="line"><span class="function">             ├─&#123;<span class="title">mongod</span>&#125;<span class="params">(<span class="number">3173</span>)</span></span></span><br><span class="line"><span class="function">             ├─&#123;<span class="title">mongod</span>&#125;<span class="params">(<span class="number">3174</span>)</span></span></span><br><span class="line"><span class="function">             ├─&#123;<span class="title">mongod</span>&#125;<span class="params">(<span class="number">3175</span>)</span></span></span><br><span class="line"><span class="function">             ├─&#123;<span class="title">mongod</span>&#125;<span class="params">(<span class="number">3177</span>)</span></span></span><br><span class="line"><span class="function">             ├─&#123;<span class="title">mongod</span>&#125;<span class="params">(<span class="number">3178</span>)</span></span></span><br><span class="line"><span class="function">             ├─&#123;<span class="title">mongod</span>&#125;<span class="params">(<span class="number">3179</span>)</span></span></span><br><span class="line"><span class="function">             ├─&#123;<span class="title">mongod</span>&#125;<span class="params">(<span class="number">3180</span>)</span></span></span><br></pre></td></tr></table></figure>

<h3 id="strace"><a href="#strace" class="headerlink" title="strace"></a>strace</h3><ul>
<li>strace 可以跟踪到一个进程产生的系统调用,包括参数，返回值，执行消耗的时间命令格式：<code>strace [options] [command]</code>。如果指定进程pid，要去掉 command</li>
</ul>
<figure class="highlight haml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">options 简单常用的参数解析</span><br><span class="line"></span><br><span class="line">-<span class="ruby">c                统计每一系统调用的所执行的时间,次数和出错的次数等</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">t                在输出中的每一行前加上时间信息</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">tt               在输出中的每一行前加上时间信息,微秒级</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">ttt              微秒级输出,以秒了表示时间</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">T                显示每一调用所耗的时间</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">e trace=         只跟踪指定的系统 调用.例如<span class="symbol">:-e</span> trace=open,close,rean,write表示只跟踪这四个系统调用，默认是 all</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">e trace=file     只跟踪有关文件操作的系统调用</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">e trace=process  只跟踪有关进程控制的系统调用</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">e trace=network  跟踪与网络有关的所有系统调用</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">e trace=ipc      跟踪所有与进程通讯有关的系统调用</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">o filename       将strace的输出写入文件filename </span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">p pid            跟踪指定的进程pid</span></span><br></pre></td></tr></table></figure>

<ul>
<li>strace 示例</li>
</ul>
<figure class="highlight vala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"># strace ls</span></span><br><span class="line"><span class="meta"># strace cat /dev/null</span></span><br><span class="line"><span class="meta"># strace -o output.txt -T -tt -e trace=all -p 28979</span></span><br></pre></td></tr></table></figure>

<ul>
<li>每一行都是一条系统调用，等号左边是系统调用的函数名及其参数，右边是该调用的返回值</li>
</ul>
<h3 id="pmap"><a href="#pmap" class="headerlink" title="pmap"></a>pmap</h3><ul>
<li>pmap 提供了进程的内存映射，pmap命令用于显示一个或多个进程的内存状态。其报告进程的地址空间和内存状态信息</li>
<li><code>pmap [options] PID</code></li>
</ul>
<figure class="highlight vbnet"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">options 参数解析</span><br><span class="line">-x extended显示扩展格式</span><br><span class="line">-d device显示设备格式</span><br><span class="line"># pmap -dx <span class="number">1</span></span><br><span class="line">Address  Kbytes Mode  Offset           Device    Mapping</span><br><span class="line"><span class="number">00110000</span> <span class="number">1480</span>K  r-x-  <span class="number">0000000000000000</span> <span class="number">008</span>:<span class="number">00005</span> /usr/<span class="keyword">lib</span>/libcrypto.so.<span class="number">1.0</span>.<span class="number">0</span></span><br><span class="line"><span class="number">00282000</span> <span class="number">80</span>K    rw--  <span class="number">0000000000015000</span> <span class="number">008</span>:<span class="number">00005</span> /usr/<span class="keyword">lib</span>/libcrypto.so.<span class="number">1.0</span>.<span class="number">0</span></span><br><span class="line"><span class="number">00296000</span> <span class="number">12</span>K    rw--  <span class="number">0000000000015000</span> <span class="number">008</span>:<span class="number">00005</span> [ anon ]</span><br><span class="line">.....</span><br><span class="line">------各项指标解析----------------------------------------</span><br><span class="line"><span class="symbol">Address:</span> 内存开始地址</span><br><span class="line"><span class="symbol">Kbytes:</span>  占用内存的字节数（KB）</span><br><span class="line"><span class="symbol">RSS:</span>     保留内存的字节数（KB）</span><br><span class="line"><span class="symbol">Dirty:</span>   脏页的字节数（包括共享和私有的）（KB）</span><br><span class="line"><span class="symbol">Mode:</span>    内存的权限：read、write、execute、<span class="keyword">shared</span>、<span class="keyword">private</span> (写时复制)</span><br><span class="line"><span class="symbol">Mapping:</span> 占用内存的文件、或[anon]（分配的内存）、或[stack]（堆栈）</span><br><span class="line"><span class="symbol">Offset:</span>  文件偏移</span><br><span class="line"><span class="symbol">Device:</span>  设备名 (major:minor)</span><br></pre></td></tr></table></figure>

<h3 id="watch"><a href="#watch" class="headerlink" title="watch"></a>watch</h3><ul>
<li>watch 可以帮助实现定时输出的命令结果，比如 netstat 没有间隔输出结果的功能。<code>watch [-options] &lt;command&gt;</code></li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">options 常用参数选项</span><br><span class="line"></span><br><span class="line"><span class="deletion">-n &lt;num&gt; watch 默认每2秒运行一下程序，可以用 -n 来指定间隔的时间  </span></span><br><span class="line"><span class="deletion">-d       watch 会高亮显示变化的区域</span></span><br><span class="line"></span><br><span class="line">切换终端：Ctrl+x     退出watch：Ctrl+g</span><br></pre></td></tr></table></figure>

<ul>
<li>watch 示例</li>
</ul>
<figure class="highlight vala"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"># watch -n 1 -d netstat -ant</span></span><br><span class="line"><span class="meta"># watch uptime</span></span><br></pre></td></tr></table></figure>

<h2 id="6-网络数据抓取"><a href="#6-网络数据抓取" class="headerlink" title="6 网络数据抓取"></a>6 网络数据抓取</h2><h3 id="tcpdump"><a href="#tcpdump" class="headerlink" title="tcpdump"></a>tcpdump</h3><ul>
<li>tcpdump 是一个运行在命令行下的抓包工具。它允许用户拦截和显示发送或收到过网络连接到该计算机的TCP/IP和其他数据包。tcpdump 适用于大多数的类Unix系统操作系统；tcpdump 命令格式为：</li>
</ul>
<figure class="highlight ldif"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># tcpdump [ -adeflnNOpqStvx ] [ -c 数量 ] [ -F 文件名 ]</span></span><br><span class="line">        [ -i 网络接口 ] [ -r 文件名] [ -s len ]</span><br><span class="line">        [ -T 类型 ] [ -w 文件名 ] [ 表达式 ]</span><br><span class="line">选项参数</span><br><span class="line"></span><br><span class="line"><span class="literal">-a       将网络地址和广播地址转变成名字</span></span><br><span class="line"><span class="literal">-d     将匹配信息包的代码以人们能够理解的汇编格式给出</span></span><br><span class="line"><span class="literal">-dd     将匹配信息包的代码以c语言程序段的格式给出</span></span><br><span class="line"><span class="literal">-ddd    将匹配信息包的代码以十进制的形式给出</span></span><br><span class="line"><span class="literal">-e    在输出行打印出数据链路层的头部信息，包括源mac和目的mac，以及网络层的协议</span></span><br><span class="line"><span class="literal">-f    将外部的Internet地址以数字的形式打印出来</span></span><br><span class="line"><span class="literal">-l    使标准输出变为缓冲行形式</span></span><br><span class="line"><span class="literal">-n    指定将每个监听到数据包中的域名转换成IP地址后显示，不把网络地址转换成名字</span></span><br><span class="line"><span class="literal">-nn：    指定将每个监听到的数据包中的域名转换成IP、端口从应用名称转换成端口号后显示</span></span><br><span class="line"><span class="literal">-t    在输出的每一行不打印时间戳</span></span><br><span class="line"><span class="literal">-v    输出一个稍微详细的信息，例如在ip包中可以包括ttl和服务类型的信息</span></span><br><span class="line"><span class="literal">-vv    输出详细的报文信息</span></span><br><span class="line"><span class="literal">-c    在收到指定的包的数目后，tcpdump就会停止</span></span><br><span class="line"><span class="literal">-F    从指定的文件中读取表达式,忽略其它的表达式</span></span><br><span class="line"><span class="literal">-i    指定监听的网络接口</span></span><br><span class="line"><span class="literal">-p：     将网卡设置为非混杂模式，不能与host或broadcast一起使用</span></span><br><span class="line"><span class="literal">-r    从指定的文件中读取包(这些包一般通过-w选项产生)</span></span><br><span class="line"><span class="literal">-w    直接将包写入文件中，并不分析和打印出来</span></span><br><span class="line"><span class="literal">-s len  len 表示从一个包中截取的字节数。0表示包不截断，抓完整的数据包。默认的话 tcpdump 只显示部分数据包,默认68字节</span></span><br><span class="line"><span class="literal">-T     将监听到的包直接解释为指定的类型的报文，常见的类型有rpc （远程过程调用）和snmp（简单网络管理协议）</span></span><br><span class="line"><span class="literal">-X       告诉tcpdump命令，需要把协议头和包内容都原原本本的显示出来（tcpdump会以16进制和ASCII的形式显示），这在进行协议分析时是绝对的利器。    </span></span><br></pre></td></tr></table></figure>

<ul>
<li><p><strong>「表达式选项」</strong> 大体可以分成三种过滤条件，“类型”、“方向”和“协议”，这三种条件的搭配组合就构成了我们的过滤表达式</p>
</li>
<li><ul>
<li><strong>「类型关键字」</strong>：主要包括host，net，port, 例如 host 210.45.114.211，指定主机 210.45.114.211，net 210.11.0.0 指明210.11.0.0是一个网络地址，port 21 指明端口号是21</li>
<li><strong>「传输方向的关键字」</strong>：主要包括src , dst ,dst or src, dst and src ,这些关键字指明了传输的方向。举例说明，src 210.45.114.211 ,指明ip包中源地址是210.45.114.211, dst net 210.11.0.0 指明目的网络地址是210.11.0.0</li>
<li><strong>「协议的关键字」</strong>：主要包括 ether,ip,ip6,arp,rarp,tcp,udp等类型，及这几个的包的协议内容。如果没有指定任何协议，则tcpdump将会监听所有协议的（更具体的请自行查看官方文档）</li>
</ul>
</li>
</ul>
<blockquote>
<p>❝</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/GNMLl94I7tekDf9vwC3IDkiagyyec5ibUPALuO45rZ21hLcsVckAibhQDK6Q9PX6j7eHHibm5NkjibxT8qZwkXUeMJg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">image.png</p>
<p>❞</p>
</blockquote>
<blockquote>
<p>❝</p>
<p>第一行:“tcpdump: verbose output suppressed, use -v or -vv for fullprotocol decode”;<br>提示使用选项 -v 和 -vv，可以看到更全的输出内容</p>
<p>❞</p>
</blockquote>
<blockquote>
<p>❝</p>
<p>第二行“listening on eth0, link-type EN10MB (Ethernet), capture size 65535bytes”；<br>我们监听的是通过 eth0 这个NIC设备的网络包，且它的链路层是基于以太网的，要抓的包大小限制是65535字节。包大小限制值可以通过-s选项来设置</p>
<p>❞</p>
</blockquote>
<blockquote>
<p>❝</p>
<p>第三行”12:40:33.569037 00:19:e0:b5:10:94 &gt; 00:1a:a0:31:39:d4, ethertypeIPv4 (0x0800),”<br>12:40:33.569037 分别对应着这个包被抓到的“时”、“分”、“秒”、“微妙”。00:19:e0:b5:10:94 &gt; 00:1a:a0:31:39:d4 表示MAC地址 00:19:e0:b5:10:94 发送到MAC地址为 00:1a:a0:31:39:d4 的主机，ethertype IPv4 (0x0800)表示Ethernet帧的协议类型为ipv4(即代码为0x0800)</p>
<p>❞</p>
</blockquote>
<blockquote>
<p>❝</p>
<p>第四行”length 66: 210.45.123.249.27236 &gt; 172.16.0.11.1111: Flags [S],seq 1624463808；<br>length 66表示以太帧长度为66。210.45.123.249.27236 表示这个包的源IP为210.45.123.249，源端口为27236，’&gt;’表示数据包的传输方向, 172.16.0.11.1111, 表示这个数据包的目的端ip为172.16.0.11,目标端口为1111，1111端口是我的一个web服务器监听端口。Flags是[S]，表明是syn建立连接包(即三次握手的第一次握手)，seq1624463808 序号为1624463808，这个其实就是TCP三次握手的第一次握手：client(210.45.123.249)发送syn请求建立连接包</p>
<p>❞</p>
</blockquote>
<blockquote>
<p>❝</p>
<p>第五行” win 8192, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0”<br>win 8192 表示窗口大小为8192字节。options[mss 1460,nop,wscale 2,nop,nop,sackOK]为tcp首部可选字段mss 1460表示mss是发送端（客户端）通告的最大报文段长度，发送端将不接收超过这个长度的TCP报文段(这个值和MTU有一定关系)。nop是一个空操作选项, wscale指出发送端使用的窗口扩大因子为2, sackOK 表示发送端支持并同意使用SACK选</p>
<p>❞</p>
</blockquote>
<ul>
<li>tcpdump 示例</li>
</ul>
<figure class="highlight autoit"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">~~ 只查目标机器端口是<span class="number">21</span>或<span class="number">80</span>的网络包，其他端口不关注</span><br><span class="line"><span class="meta"># tcpdump -i eth0 -c 10 <span class="string">&#x27;dst port 21 or dst port 80&#x27;</span></span></span><br><span class="line">~~ 想获取<span class="number">172.16</span><span class="number">.10</span><span class="number">.11</span> 和 google.com之间建立TCP三次握手中带有SYN标记位的网络包.</span><br><span class="line"><span class="meta"># tcpdump -i eth0 <span class="string">&#x27;host 172.16.0.11 and host google.com and tcp[13]&amp;2!=0&#x27;</span> -c 3 -nn</span></span><br></pre></td></tr></table></figure>

<ul>
<li>最后一命令的 tcp[13]&amp;2!=0 可能有点怪，这里解析一下，标志位(URG,ACK,PSH,RST,SYN,FIN)在 tcp头部的第 13 个字节中，而 SYN 则在低第二位（xxxxxx10，十进制是2），和2进行与操作，即可判断报文是否 syn 报文</li>
</ul>
<h3 id="nc"><a href="#nc" class="headerlink" title="nc"></a>nc</h3><ul>
<li>nc 命令实现任意TCP/UDP端口的侦听，nc可以作为 server 以TCP或UDP方式侦听指定端口。nc 也可以作为 client 发起TCP或UDP连接</li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">options 常用参数</span><br><span class="line"><span class="deletion">-l    用于指定nc将处于侦听模式。指定该参数，则意味着nc被当作server，侦听并接受连接，而非向其它地址发起连接。</span></span><br><span class="line"><span class="deletion">-s    指定发送数据的源IP地址，适用于多网卡机</span></span><br><span class="line"><span class="deletion">-u    指定nc使用UDP协议，默认为TCP</span></span><br><span class="line"><span class="deletion">-v    输出交互或出错信息，新手调试时尤为有用</span></span><br><span class="line"><span class="deletion">-w    超时秒数，后面跟数字</span></span><br><span class="line"><span class="deletion">-z    使用 Zero-I/O mode，只在扫描通信端口时使用</span></span><br></pre></td></tr></table></figure>

<ul>
<li>nc 示例</li>
</ul>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">~~ 端口扫描</span><br><span class="line"><span class="comment"># nc -v -w 2 192.168.2.34 -z 21-24</span></span><br><span class="line">nc: connect <span class="keyword">to</span> 192.168.2.34<span class="built_in"> port </span>21 (tcp) failed:<span class="built_in"> Connection </span>refused<span class="built_in"></span></span><br><span class="line"><span class="built_in">Connection </span><span class="keyword">to</span> 192.168.2.34 22<span class="built_in"> port </span>[tcp/ssh] succeeded!</span><br><span class="line"></span><br><span class="line">~~ 简单聊天工具 在 192.168.2.34 服务端监听 1211</span><br><span class="line"><span class="comment"># nc -l 1211</span></span><br><span class="line">~~ 在 192.168.2.33 上 连接 34 的 1211端口</span><br><span class="line"><span class="comment"># nc 192.168.2.34 1211</span></span><br></pre></td></tr></table></figure>

<h3 id="curl"><a href="#curl" class="headerlink" title="curl"></a>curl</h3><ul>
<li>curl 是一款很强大的 http 命令行工具。它支持文件的上传和下载。命令格式：<code>curl [option] [url]</code></li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">option 常用参数</span><br><span class="line"></span><br><span class="line"><span class="deletion">-A/--user-agent &lt;string&gt;   设置用户代理发送给服务器</span></span><br><span class="line"><span class="deletion">-b &lt;name=string/file&gt;      cookie字符串或文件读取位置</span></span><br><span class="line"><span class="deletion">-c &lt;file&gt;                  操作结束后把cookie写入到这个文件中</span></span><br><span class="line"><span class="deletion">-C &lt;offset&gt;                断点续转</span></span><br><span class="line"><span class="deletion">-D &lt;file&gt;                  把header信息写入到该文件中</span></span><br><span class="line"><span class="deletion">-e                         来源网址(伪造referer)</span></span><br><span class="line"><span class="deletion">-o                         把输出写到该文件中</span></span><br><span class="line"><span class="deletion">-O                         把输出写到该文件中，保留远程文件的文件名</span></span><br><span class="line"><span class="deletion">-r &lt;range&gt;                 分块下载来自HTTP/1.1或FTP服务器 range字节</span></span><br><span class="line"><span class="deletion">-T &lt;file&gt;                  上传文件</span></span><br><span class="line"><span class="deletion">-u &lt;user[:password]&gt;       设置服务器的用户和密码</span></span><br><span class="line"><span class="deletion">-L                         参数会让 HTTP 请求跟随服务器的重定向。curl 默认不重定向</span></span><br><span class="line"><span class="deletion">-x &lt;host:port&gt;             在给定的端口上使用HTTP代理</span></span><br><span class="line"><span class="deletion">-#                         进度条显示当前的传送状态</span></span><br><span class="line"><span class="deletion">-X                         指定 HTTP 请求的方法</span></span><br><span class="line"><span class="deletion">-d                         POST方式传送数据(默认是application/x-www-form-urlencoded)</span></span><br><span class="line"><span class="deletion">-H/--header &lt;line&gt;         自定义头信息传递给服务器</span></span><br></pre></td></tr></table></figure>

<ul>
<li>curl 示例</li>
</ul>
<figure class="highlight clean"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">~~ 显示下载进度条</span><br><span class="line"># curl -# -O http:<span class="comment">//www.linux.com/lwl.jpg</span></span><br><span class="line">~~ 上传文件</span><br><span class="line"># curl -T lwl.jpg -u 用户名:密码 ftp:<span class="comment">//www.linux.com/img/</span></span><br><span class="line">~~ 发出 POST 请求</span><br><span class="line"># curl -X POST https:<span class="comment">//www.example.com</span></span><br><span class="line">~~ data.json 是json 数据</span><br><span class="line"># curl localhost:<span class="number">3000</span>/api/json -X POST -d @data.json --header <span class="string">&quot;Content-Type: application/json&quot;</span></span><br></pre></td></tr></table></figure>

<h3 id="wget"><a href="#wget" class="headerlink" title="wget"></a>wget</h3><ul>
<li>wget 是一个下载文件的工具，对于Linux用户是必不可少的工具，因为我们经常要下载一些软件或从远程服务器恢复备份到本地服务器。wget支持HTTP，HTTPS和FTP协议。命令格式：<code>wget [-options] [url]</code></li>
</ul>
<figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">options 常用参数解析</span><br><span class="line"></span><br><span class="line">-O <span class="tag">&lt;fileName&gt;</span>        把文档写到FILE文件中</span><br><span class="line">-c                   (断点续传)接着下载没下载完的文件</span><br><span class="line">-P filePath          将文件保存到 filePath 目录 </span><br><span class="line">-b                   后台下载</span><br><span class="line"></span><br><span class="line">TP 选项:</span><br><span class="line">--<span class="attr">ftp-user=</span><span class="keyword">USER</span>         <span class="title">设置 ftp</span> 用户名为 <span class="keyword">USER</span></span><br><span class="line"><span class="title">--ftp-password</span>=PASS     设置 ftp 密码为 PASS</span><br></pre></td></tr></table></figure>

<ul>
<li>wget 示例</li>
</ul>
<figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="symbol">~~ wget -b 后台下载</span></span><br><span class="line"><span class="symbol"># wget -c -b -O wordpress.zip https</span>:<span class="comment">//cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz</span></span><br><span class="line"><span class="symbol">~~ ftp 下载 csc.txt 文件</span></span><br><span class="line"><span class="symbol"># wget --ftp-user=baidu  --ftp-password=123 ftp</span>:<span class="comment">//192.168.19.1/lwl/csc.txt</span></span><br></pre></td></tr></table></figure>

<h2 id="7-shell-脚本命令"><a href="#7-shell-脚本命令" class="headerlink" title="7 shell 脚本命令"></a>7 shell 脚本命令</h2><h3 id="shell-程序语法"><a href="#shell-程序语法" class="headerlink" title="shell 程序语法"></a>shell 程序语法</h3><ul>
<li>要想写shell 脚本，则需要熟悉下 shell 程序基本语法</li>
<li>之前写的一篇文章：<a target="_blank" rel="noopener" href="http://mp.weixin.qq.com/s?__biz=MzU3NDM0NDg5MA==&mid=2247485939&idx=1&sn=8473f4d51b3d07f8d326b5f0ce605b67&chksm=fd329226ca451b301c6e7af969cdf3c879b3bf470ab18f3f853aeebc6e0ca9880573809ad181&scene=21#wechat_redirect">shell教程及脚本编写</a></li>
</ul>
<h3 id="sed"><a href="#sed" class="headerlink" title="sed"></a>sed</h3><ul>
<li>如果涉及到文本处理，可试试 sed，sed 采用的是流编辑模式，在 sed 处理数据之前，需要预先提供一组规则，sed 会按照此规则来编辑数据</li>
<li>之前写的一篇文章：<a target="_blank" rel="noopener" href="http://mp.weixin.qq.com/s?__biz=MzU3NDM0NDg5MA==&mid=2247485895&idx=1&sn=70f859a738792ddb56fae5e306171805&chksm=fd329212ca451b04ed65ecbd3db17347ec277fb0a42489289f45e7b84c69ae7a32731cd54d0b&scene=21#wechat_redirect">sed教程-linux命令</a></li>
</ul>
<h3 id="awk"><a href="#awk" class="headerlink" title="awk"></a>awk</h3><ul>
<li>awk 同样适合处理文本，且更强大；和 sed 命令类似，awk 命令也是逐行扫描文件，寻找含有目标文本的行，如果匹配成功，则会在该行上执行用户想要的操作；反之，则不对行做任何处理</li>
<li>之前写的一篇文章：<a target="_blank" rel="noopener" href="http://mp.weixin.qq.com/s?__biz=MzU3NDM0NDg5MA==&mid=2247485924&idx=1&sn=e0aad26ece8e4b63b14678b8f32d264e&chksm=fd329231ca451b27aa28fe065b436db8e33744b465cc1831426f18a44baa30e3f676884594dc&scene=21#wechat_redirect">awk教程-linux命令</a></li>
</ul>
<h3 id="xargs"><a href="#xargs" class="headerlink" title="xargs"></a>xargs</h3><ul>
<li>xargs 是一个强有力的命令，在 linux 命令管道传递中，它能够捕获上一个命令的输出，然后传递给另外一个命令。xargs 默认的命令是 echo，这意味着通过管道传递给 xargs 的输入将会包含换行和空白，不过通过 xargs 的处理，换行和空白将被空格取代</li>
<li>命令格式：<code>command |xargs [-options] nextCommand</code></li>
</ul>
<figure class="highlight haml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">options 参数解释</span><br><span class="line"></span><br><span class="line">-<span class="ruby">e flag 或 -E flag    flag必须是一个以空格分隔的标志，当xargs分析到含有flag这个标志的时候就停止</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">r no-run-<span class="keyword">if</span>-empty    当xargs的输入为空的时候则停止xargs，不再去执行</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">t                    表示先打印命令，然后再执行</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">p                    每执行一次xargs 后面跟随的 nextCommand 时，询问一次用户</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">n num                将输出数据用<span class="string">&quot;空格&quot;</span>分割成多个参数，再按n个一组分批作为 nextCommand 执行时的参数</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">L num 或 -l num      从标准输入一次读取 num 行送给 nextCommand 命令执行</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">i 或 -I              将一行一行赋值给占位符 &#123;&#125;，在接下来的command里用 &#123;&#125; 替换数据</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">s num                命令行的最大字符数，指的是 xargs 后面那个命令的最大命令行字符数</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">d delim              指定分隔符，默认的xargs分隔符是回车（换行键），这里修改的是xargs的分隔符</span></span><br></pre></td></tr></table></figure>

<ul>
<li>xargs 示例</li>
</ul>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">~~ 复制所有图片文件到 <span class="regexp">/data/im</span>ages 目录下</span><br><span class="line"># ls *.jpg | xargs -n1 -I &#123;&#125; cp &#123;&#125; <span class="regexp">/data/im</span>ages</span><br><span class="line">~~ 查找所有的 jpg 文件，并且压缩它们</span><br><span class="line"># <span class="keyword">find</span> . -type f -name <span class="string">&quot;*.jpg&quot;</span> -<span class="keyword">print</span> | xargs tar -czvf images.tar.gz</span><br></pre></td></tr></table></figure>

<h2 id="8-jvm-常用命令"><a href="#8-jvm-常用命令" class="headerlink" title="8 jvm 常用命令"></a>8 jvm 常用命令</h2><h3 id="jps"><a href="#jps" class="headerlink" title="jps"></a>jps</h3><ul>
<li>java 版的 ps 命令，查看java进程及其相关的信息，如果想找到一个 java 进程的 pid，那可以用 jps 命令替代linux中的 ps 命令了，命令格式：<code>jps [-options] [hostIP]</code>。如果要查看其他 hostIP 机器上的jvm进程，需要在待查看机器上启动 jstatd</li>
</ul>
<figure class="highlight ada"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">options 参数解释</span><br><span class="line"></span><br><span class="line">-l : 输出主类全名或<span class="type">jar</span>路径</span><br><span class="line">-q : 只输出<span class="type">LVMID</span></span><br><span class="line">-m : 输出<span class="type">JVM</span>启动时传递给main()的参数</span><br><span class="line">-v : 输出<span class="type">JVM</span>启动时显示指定的JVM参数</span><br></pre></td></tr></table></figure>

<ul>
<li>jps 示例</li>
</ul>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"> <span class="comment"># jps -lmv</span></span><br><span class="line"><span class="number">18884</span> <span class="regexp">/opt/</span>app<span class="regexp">/spring-boot/</span>order.jar --spring.profiles.active=test</span><br><span class="line"><span class="number">39812</span> <span class="regexp">/opt/</span>app<span class="regexp">/spring-boot/u</span>ser.jar --spring.profiles.active=test</span><br></pre></td></tr></table></figure>

<h3 id="jinfo"><a href="#jinfo" class="headerlink" title="jinfo"></a>jinfo</h3><ul>
<li>jinfo 是用来查看JVM参数和动态修改部分JVM参数的命令;命令格式：<code>jinfo [-option] &lt;pid&gt;</code></li>
</ul>
<figure class="highlight sqf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">options 参数解释</span><br><span class="line"></span><br><span class="line">-<span class="built_in">flag</span> &lt;<span class="built_in">name</span>&gt;          打印指定名称的参数</span><br><span class="line">-<span class="built_in">flag</span> [+|-]&lt;<span class="built_in">name</span>&gt;     打开或关闭参数</span><br><span class="line">-<span class="built_in">flag</span> &lt;<span class="built_in">name</span>&gt;=&lt;value&gt;  设置参数</span><br><span class="line">-flags                打印所有参数</span><br><span class="line">-sysprops             打印系统配置</span><br><span class="line">默认是 flags 和 sysprops</span><br></pre></td></tr></table></figure>

<ul>
<li>jinfo 示例</li>
</ul>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># jinfo -flags 19092</span></span><br><span class="line">Attaching <span class="keyword">to</span> process ID 19092, please wait<span class="built_in">..</span>.</span><br><span class="line">Debugger attached successfully.<span class="built_in"></span></span><br><span class="line"><span class="built_in">Server </span>compiler detected.</span><br><span class="line">JVM version is 25.181-b13</span><br><span class="line">Non-default VM flags: -XX:-BytecodeVerificationLocal -XX:-BytecodeVerificationRemote -XX:<span class="attribute">CICompilerCount</span>=4 -XX:<span class="attribute">InitialHeapSize</span>=266338304 -XX:+ManagementServer -XX:Max</span><br><span class="line"><span class="attribute">HeapSize</span>=4229955584 -XX:<span class="attribute">MaxNewSize</span>=1409810432 -XX:<span class="attribute">MinHeapDeltaBytes</span>=524288 -XX:<span class="attribute">NewSize</span>=88604672 -XX:<span class="attribute">OldSize</span>=177733632 -XX:<span class="attribute">TieredStopAtLevel</span>=1 -XX:+UseCompressedClassP ointers -XX:+UseCompressedOops </span><br><span class="line"><span class="built_in">..</span><span class="built_in">..</span>.</span><br></pre></td></tr></table></figure>

<h3 id="jstat"><a href="#jstat" class="headerlink" title="jstat"></a>jstat</h3><ul>
<li>jstat 命令是使用频率比较高的命令，主要用来查看JVM运行时的状态信息，包括内存状态、垃圾回收等；命令格式：<code>jstat [-option] pid [interval] [count]</code>，pid 是进程id，interval 是打印间隔时间（毫秒），count是打印次数（默认一直打印）</li>
</ul>
<figure class="highlight haml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">option 参数解释</span><br><span class="line"></span><br><span class="line">-<span class="ruby"><span class="class"><span class="keyword">class</span>            : <span class="title">class</span> <span class="title">loader</span>的行为统计</span></span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">compiler         : HotSpt JIT编译器行为统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">gc               : 垃圾回收堆的行为统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">gccapacity       : 各个垃圾回收代容量(young,old,perm)和他们相应的空间统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">gcutil           : 垃圾回收统计概述</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">gccause          : 垃圾收集统计概述（同-gcutil），附加最近两次垃圾回收事件的原因</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">gcnew            : 新生代行为统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">gcnewcapacity    : 新生代与其相应的内存空间的统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">gcold            : 年老代和永生代行为统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">gcoldcapacity    : 年老代行为统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">gcpermcapacity   : 永生代行为统计</span></span><br><span class="line"><span class="ruby"></span>-<span class="ruby">printcompilation : HotSpot编译方法统计</span></span><br></pre></td></tr></table></figure>

<ul>
<li>jstat 示例</li>
</ul>
<figure class="highlight mathematica"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">#</span> <span class="variable">jstat</span> <span class="operator">-</span><span class="variable">gcutil</span> <span class="number">18884</span></span><br><span class="line"><span class="variable">S0</span>     <span class="variable">S1</span>     <span class="built_in">E</span>      <span class="built_in">O</span>      <span class="variable">M</span>     <span class="variable">CCS</span>    <span class="variable">YGC</span>     <span class="variable">YGCT</span>    <span class="variable">FGC</span>    <span class="variable">FGCT</span>     <span class="variable">GCT</span>   </span><br><span class="line"><span class="number">0.00</span>  <span class="number">84.14</span>  <span class="number">19.93</span>  <span class="number">45.77</span>  <span class="number">91.32</span>  <span class="number">87.65</span>    <span class="number">641</span>   <span class="number">18.311</span>     <span class="number">6</span>    <span class="number">3.512</span>   <span class="number">21.824</span></span><br><span class="line"></span><br><span class="line"><span class="operator">------</span>各项指标解析<span class="operator">----------------------------------------</span></span><br><span class="line"><span class="variable">S0</span> 第 <span class="number">0</span> 个 <span class="variable">survivor</span>（幸存区）使用的百分比</span><br><span class="line"><span class="variable">S1</span> 第 <span class="number">1</span> 个 <span class="variable">survivor</span>（幸存区）使用的百分比</span><br><span class="line"><span class="built_in">E</span> <span class="variable">Eden</span> 区使用内存的百分比</span><br><span class="line"><span class="built_in">O</span> 老生代内存使用的百分比</span><br><span class="line"><span class="variable">P</span><span class="operator">/</span><span class="variable">M</span> <span class="variable">PermGen</span><span class="operator">/</span><span class="variable">MetaSpace</span> 的内存使用百分比</span><br><span class="line"><span class="variable">YGC</span> 程序启动以来 <span class="variable">Young</span> <span class="variable">GC</span> 发生的次数</span><br><span class="line"><span class="variable">YGCT</span> 程序启动以来 <span class="variable">Young</span> <span class="variable">GC</span> 共消耗的时间<span class="punctuation">(</span><span class="variable">s</span><span class="punctuation">)</span></span><br><span class="line"><span class="variable">FGC</span> 程序启动以来 <span class="built_in">Full</span> <span class="variable">GC</span> 发生的次数</span><br><span class="line"><span class="variable">FGCT</span> 程序启动以来 <span class="built_in">Full</span> <span class="variable">GC</span> 共消耗的时间<span class="punctuation">(</span><span class="variable">s</span><span class="punctuation">)</span></span><br><span class="line"><span class="variable">GCT</span> 程序启动以来 <span class="variable">GC</span> 的总用时<span class="punctuation">(</span><span class="variable">s</span><span class="punctuation">)</span></span><br></pre></td></tr></table></figure>

<h3 id="jstack"><a href="#jstack" class="headerlink" title="jstack"></a>jstack</h3><ul>
<li>jstack 是用来查看 jvm 线程快照的命令，线程快照是当前JVM线程正在执行的方法堆栈集合。使用 jstack 命令可以定位线程出现长时间卡顿的原因，例如死锁，死循环等。jstack 还可以查看程序崩溃时生成的 core 文件中的 stack 信息；命令格式：<code>jstack [-Flm] &lt;pid&gt;</code></li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">option 参数解释</span><br><span class="line"></span><br><span class="line"><span class="deletion">-F  当使用jstack &lt;pid&gt;无响应时，强制输出线程堆栈</span></span><br><span class="line"><span class="deletion">-m  同时输出java和本地堆栈(混合模式)</span></span><br><span class="line"><span class="deletion">-l  额外显示锁信息 (小写l)</span></span><br></pre></td></tr></table></figure>

<ul>
<li>jstack 示例，查看 pid = 1211 的线程栈</li>
</ul>
<figure class="highlight excel"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># jstack -l <span class="number">1211</span></span><br><span class="line"><span class="string">&quot;DiscoveryClient-CacheRefreshExecutor-0&quot;</span> #<span class="number">146</span> daemon prio=<span class="number">5</span> os_prio=<span class="number">0</span> tid=<span class="number">0</span>x000000002ba2c000 nid</span><br><span class="line">=<span class="number">0</span>x4fe4 waiting on condition [<span class="number">0</span>x000000002cade000]</span><br><span class="line">   java.lang.Thread.Sta<span class="symbol">te:</span> WAITING (parking)</span><br><span class="line">        at sun.misc.Unsafe.park(Native Method)</span><br><span class="line">        - parking to wait for  &lt;<span class="number">0</span>x00000006c775dc60&gt; (a java.util.concurrent.SynchronousQueue$Tra</span><br><span class="line">nsferStack)</span><br><span class="line">......</span><br></pre></td></tr></table></figure>

<h3 id="jmap"><a href="#jmap" class="headerlink" title="jmap"></a>jmap</h3><ul>
<li>jmap 是用来生成堆dump文件 或 查看堆相关的各类信息的命令，例如查看 finalize 执行队列，heap 的详细信息和使用情况；命令格式：<code>jmap [-option] &lt;pid&gt;</code></li>
</ul>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">option 参数解释</span><br><span class="line"></span><br><span class="line">-heap 打印java heap摘要</span><br><span class="line">-histo[:live] 打印堆中的java对象统计信息</span><br><span class="line">-clstats 打印类加载器统计信息</span><br><span class="line">-finalizerinfo 打印在f-queue中等待执行finalizer方法的对象</span><br><span class="line">-<span class="keyword">dump</span>:&lt;<span class="keyword">dump</span>-<span class="keyword">options</span>&gt; 生成java堆的<span class="keyword">dump</span>文件</span><br><span class="line">      <span class="keyword">dump</span>-<span class="keyword">options</span>:</span><br><span class="line">      live 只转储存活的对象，如果没有指定则转储所有对象</span><br><span class="line">      format=b 二进制格式</span><br><span class="line">      <span class="keyword">file</span>=&lt;<span class="keyword">file</span>&gt; 转储文件到 &lt;<span class="keyword">file</span>&gt;</span><br><span class="line">-F 如果jvm挂起，可用-F强制执行选项，会影响java 服务</span><br></pre></td></tr></table></figure>

<ul>
<li>jmap 示例，dump 出 pid=1211 java进程的内存堆文件</li>
</ul>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># jmap -<span class="keyword">dump</span>:live,format=b,<span class="keyword">file</span>=<span class="keyword">dump</span>.hprof <span class="number">1211</span></span><br><span class="line">Dumping heap to <span class="regexp">/home/</span>lwl/<span class="keyword">dump</span>.hprof ...</span><br><span class="line">Heap <span class="keyword">dump</span> <span class="keyword">file</span> created</span><br></pre></td></tr></table></figure>

      
    </div>
<div>
  
</div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wan-lei8.gitee.io/2022/01/25/JVM%E8%B0%83%E4%BC%98/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员西桐">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2022/01/25/JVM%E8%B0%83%E4%BC%98/" class="post-title-link" itemprop="url">JVM调优</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-01-25 10:49:54 / 修改时间：10:50:36" itemprop="dateCreated datePublished" datetime="2022-01-25T10:49:54+08:00">2022-01-25</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="文章总体结构"><a href="#文章总体结构" class="headerlink" title="文章总体结构"></a>文章总体结构</h2><p>本文中，我们将按照如下结构介绍JVM的整体架构和调优参数。</p>
          <!--noindex-->
            <div class="post-button">
              <a class="btn" href="/2022/01/25/JVM%E8%B0%83%E4%BC%98/#more" rel="contents">
                阅读全文 &raquo;
              </a>
            </div>
          <!--/noindex-->
        
      
    </div>
<div>
  
</div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wan-lei8.gitee.io/2022/01/24/%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BC%98%E5%8C%96%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BB%8E%E5%93%AA%E4%BA%9B%E7%BB%B4%E5%BA%A6%E5%85%A5%E6%89%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员西桐">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2022/01/24/%E6%95%B0%E6%8D%AE%E5%BA%93%E4%BC%98%E5%8C%96%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BB%8E%E5%93%AA%E4%BA%9B%E7%BB%B4%E5%BA%A6%E5%85%A5%E6%89%8B/" class="post-title-link" itemprop="url">数据库优化，可以从哪些维度入手</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-01-24 17:02:43 / 修改时间：17:03:26" itemprop="dateCreated datePublished" datetime="2022-01-24T17:02:43+08:00">2022-01-24</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>当有人问你如何对数据库进行优化时，很多人第一反应想到的就是SQL优化，如何创建索引，如何改写SQL，他们把数据库优化与SQL优化划上了等号。</p>
<p>当然这不能算是完全错误的回答，只不过思考的角度稍微片面了些，太“<strong>程序员思维</strong>”化了，没有站在更高层次来思考回答。那今天我们就将视角拔高，站在架构的角度来聊聊这一问题，<strong>数据库优化可以从哪些维度入手？</strong></p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/PxMzT0Oibf4iaicicsWhJbntSpBuNORfVogZUBOOAaRUPb6icJ8Z7QpcPppzsELhnhlQ2xaEWBQADUEPzob4u24S29A/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>正如上图所示，数据库优化可以从架构优化，硬件优化，DB优化，SQL优化四个维度入手。</p>
<p>此上而下，位置越靠前优化越明显，对数据库的性能提升越高。我们常说的SQL优化反而是对性能提高最小的优化。</p>
<p>接下来我们再看看每种优化该如何实施。</p>
<h2 id="架构优化"><a href="#架构优化" class="headerlink" title="架构优化"></a>架构优化</h2><p>一般来说在高并发的场景下对架构层进行优化其效果最为明显，常见的优化手段有：分布式缓存，读写分离，分库分表等，每种优化手段又适用于不同的应用场景。</p>
<h3 id="分布式缓存"><a href="#分布式缓存" class="headerlink" title="分布式缓存"></a>分布式缓存</h3><p>有句老话说的好，性能不够，缓存来凑。当需要在架构层进行优化时我们第一时间就会想到缓存这个神器，在应用与数据库之间增加一个缓存服务，如Redis或Memcache。</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/PxMzT0Oibf4iaicicsWhJbntSpBuNORfVogZsqbXm4MvOrY4Zp9nzzRjQ4snXthzdKu3V53vibG8YKjtdM1RFOohPZg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>当接收到查询请求后，我们先查询缓存，判断缓存中是否有数据，有数据就直接返回给应用，如若没有再查询数据库，并加载到缓存中，这样就大大减少了对数据库的访问次数，自然而然也提高了数据库性能。</p>
<p>不过需要注意的是，引入分布式缓存后系统需要考虑如何应对<strong>缓存穿透、缓存击穿和缓存雪崩</strong>的问题。</p>
<blockquote>
<p>“</p>
<p>简单理解一下 缓存穿透、缓存击穿 和 缓存雪崩</p>
<p>缓存穿透：它是指当用户在查询一条数据的时候，而此时数据库和缓存都没有关于这条数据的任何记录。这条数据在缓存中没找到就会向数据库请求获取数据。它拿不到数据时，是会一直查询数据库，这样会对数据库的访问造成很大的压力。</p>
<p>缓存击穿：一个热点key刚好在某个时间点失效了，但是这时候突然来了大量对这个key的并发访问请求，导致大并发请求直接穿透缓存直达数据库，瞬间对数据库的访问压力增大。</p>
<p>缓存雪崩：某一个时间段内，缓存集中过期失效，如果这个时间段内有大量请求，而查询数据量巨大，所有的请求都会达到存储层，存储层的调用量会暴增，引起数据库压力过大甚至宕机。</p>
<p>”</p>
</blockquote>
<h3 id="读写分离"><a href="#读写分离" class="headerlink" title="读写分离"></a>读写分离</h3><p>一主多从，读写分离，主动同步，是一种常见的数据库架构优化手段。</p>
<p>一般来说当你的应用是<strong>读多写少</strong>，数据库扛不住<strong>读压力</strong>的时候，采用读写分离，通过增加从库数量可以线性提升系统读性能。</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/PxMzT0Oibf4iaicicsWhJbntSpBuNORfVogZURWyaWhvNTLrMrfjY8Jia74eibjib9618AN9zLEyZCwKywrahLibGoNCAw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>主库，提供数据库写服务；从库，提供数据库读能力；主从之间，通过binlog同步数据。</p>
<p>当准备实施读写分离时，为了保证高可用，需要实现故障的自动转移，主从架构会有潜在主从不一致性问题。</p>
<h3 id="水平切分"><a href="#水平切分" class="headerlink" title="水平切分"></a>水平切分</h3><p>水平切分，也是一种常见的数据库架构优化手段。</p>
<p>当你的应用<strong>业务数据量很大</strong>，<strong>单库容量成为性能瓶颈后</strong>，采用水平切分，可以降低数据库单库容量，提升数据库写性能。</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/PxMzT0Oibf4iaicicsWhJbntSpBuNORfVogZOak7Sia3jBewQjvhA7ynrIhXVSgQu91LYuCo1GTQvicHcFgE7JNickxtQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>当准备实施水平切分时，需要结合实际业务选取合理的分片键（sharding-key），有时候为了解决非分片键查询问题还需要将数据写到单独的查询组件，如ElasticSearch。</p>
<h3 id="架构优化小结"><a href="#架构优化小结" class="headerlink" title="架构优化小结"></a>架构优化小结</h3><ol>
<li>读写分离主要是用于解决 “数据库读性能问题”</li>
<li>水平切分主要是用于解决“数据库数据量大的问题”</li>
<li>分布式缓存架构可能比读写分离更适用于高并发、大数据量大场景。</li>
</ol>
<h2 id="硬件优化"><a href="#硬件优化" class="headerlink" title="硬件优化"></a>硬件优化</h2><p>我们使用数据库，不管是读操作还是写操作，最终都是要访问磁盘，所以说磁盘的性能决定了数据库的性能。一块PCIE固态硬盘的性能是普通机械硬盘的几十倍不止。这里我们可以从<strong>吞吐率</strong>、<strong>IOPS</strong>两个维度看一下机械硬盘、普通固态硬盘、PCIE固态硬盘之间的性能指标。</p>
<p><strong>吞吐率：单位时间内读写的数据量</strong></p>
<ul>
<li>机械硬盘：约100MB/s ～ 200MB/s</li>
<li>普通固态硬盘：200MB/s ～ 500MB/s</li>
<li>PCIE固态硬盘：900MB/s ～ 3GB/s</li>
</ul>
<p><strong>IOPS：每秒IO操作的次数</strong></p>
<ul>
<li>机械硬盘：100 ～200</li>
<li>普通固态硬盘：30000 ～ 50000</li>
<li>PCIE固态硬盘：数十万</li>
</ul>
<p>通过上面的数据可以很直观的看到不同规格的硬盘之间的性能差距非常大，当然性能更好的硬盘价格会更贵，在资金充足并且迫切需要提升数据库性能时，尝试更换一下数据库的硬盘不失为一个非常好的举措，你之前遇到SQL执行缓慢问题在你更换硬盘后很可能将不再是问题。</p>
<h2 id="DB优化"><a href="#DB优化" class="headerlink" title="DB优化"></a>DB优化</h2><p>SQL执行慢有时候不一定完全是SQL问题，手动安装一台数据库而不做任何参数调整，再怎么优化SQL都无法让其性能最大化。要让一台数据库实例完全发挥其性能，首先我们就得先优化数据库的实例参数。</p>
<p>数据库实例参数优化遵循三句口诀：<strong>日志不能小、缓存足够大、连接要够用。</strong></p>
<p>数据库事务提交后需要将事务对数据页的修改刷（ fsync）到磁盘上，才能保证数据的持久性。这个刷盘，是一个随机写，性能较低，如果每次事务提交都要刷盘，会极大影响数据库的性能。数据库在架构设计中都会采用如下两个优化手法：</p>
<ul>
<li>先将事务写到日志文件RedoLog（WAL），将随机写优化成顺序写</li>
<li>加一层缓存结构Buffer，将单次写优化成顺序写</li>
</ul>
<p>所以日志跟缓存对数据库实例尤其重要。而连接如果不够用，数据库会直接抛出异常，系统无法访问。</p>
<p>接下来我们以Oracle、MySQL（InnoDB）、POSTGRES、达梦为例，看看每种数据库的参数该如何配置。</p>
<h3 id="Oracle"><a href="#Oracle" class="headerlink" title="Oracle"></a>Oracle</h3><table>
<thead>
<tr>
<th align="left">参数分类</th>
<th align="left">参数名</th>
<th align="left">参数值</th>
<th align="left">备注</th>
</tr>
</thead>
<tbody><tr>
<td align="left">数据缓存</td>
<td align="left">SGA_TAGET、MEMORY_TARGET</td>
<td align="left">物理内存70-80%</td>
<td align="left">越大越好</td>
</tr>
<tr>
<td align="left">数据缓存</td>
<td align="left">DB_CACHE_SIZE</td>
<td align="left">物理内存70-80%</td>
<td align="left">越大越好</td>
</tr>
<tr>
<td align="left">SQL解析</td>
<td align="left">SHARED_POOL_SIZE</td>
<td align="left">4-16G</td>
<td align="left">不建议设置过大</td>
</tr>
<tr>
<td align="left">监听及连接</td>
<td align="left">PROCESSES、SESSIONS、OPEN_CURSORS</td>
<td align="left">根据业务需求设置</td>
<td align="left">一般为业务预估连接数的120%</td>
</tr>
<tr>
<td align="left">其他</td>
<td align="left">SESSION_CACHED_CURSORS</td>
<td align="left">大于200</td>
<td align="left">软软解析</td>
</tr>
</tbody></table>
<h3 id="MySQL"><a href="#MySQL" class="headerlink" title="MySQL"></a>MySQL</h3><table>
<thead>
<tr>
<th align="left">参数分类</th>
<th align="left">参数名</th>
<th align="left">参数值</th>
<th align="left">备注</th>
</tr>
</thead>
<tbody><tr>
<td align="left">数据缓存</td>
<td align="left">INNODB_BUFFER_POOL_SIZE</td>
<td align="left">物理内存50-80%</td>
<td align="left">一般来说越大性能越好</td>
</tr>
<tr>
<td align="left">日志相关</td>
<td align="left">Innodb_log_buffer_size</td>
<td align="left">16-32M</td>
<td align="left">根据运行情况调整</td>
</tr>
<tr>
<td align="left">日志相关</td>
<td align="left">sync_binlog</td>
<td align="left">1、100、0</td>
<td align="left">1安全性最好</td>
</tr>
<tr>
<td align="left">监听及连接</td>
<td align="left">max_connections</td>
<td align="left">根据业务情况调整</td>
<td align="left">可以预留一部分值</td>
</tr>
<tr>
<td align="left">文件读写性能</td>
<td align="left">innodb_flush_log_at_trx_commit</td>
<td align="left">2</td>
<td align="left">安全和性能的折中考虑</td>
</tr>
<tr>
<td align="left">其他</td>
<td align="left">wait_timeout，interactive_timeout</td>
<td align="left">28800</td>
<td align="left">避免应用连接定时中断</td>
</tr>
</tbody></table>
<h3 id="POSTGRES"><a href="#POSTGRES" class="headerlink" title="POSTGRES"></a>POSTGRES</h3><table>
<thead>
<tr>
<th align="left">参数分类</th>
<th align="left">参数名</th>
<th align="left">参数值</th>
<th align="left">备注</th>
</tr>
</thead>
<tbody><tr>
<td align="left">数据缓存</td>
<td align="left">SHARED_BUFFERS</td>
<td align="left">物理内存10-25%</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">数据缓存</td>
<td align="left">CACHE_BUFFER_SIZE</td>
<td align="left">物理内存50-60%</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">日志相关</td>
<td align="left">wal_buffer</td>
<td align="left">8-64M</td>
<td align="left">不建议设置过大过小</td>
</tr>
<tr>
<td align="left">监听及连接</td>
<td align="left">max_connections</td>
<td align="left">根据业务情况调整</td>
<td align="left">一般为业务预估连接数的120%</td>
</tr>
<tr>
<td align="left">其他</td>
<td align="left">maintenance_work_mem</td>
<td align="left">512M或更大</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">其他</td>
<td align="left">work_mem</td>
<td align="left">8-16M</td>
<td align="left">原始配置1M过小</td>
</tr>
<tr>
<td align="left">其他</td>
<td align="left">checkpoint_segments</td>
<td align="left">32或者更大</td>
<td align="left"></td>
</tr>
</tbody></table>
<h3 id="达梦数据库"><a href="#达梦数据库" class="headerlink" title="达梦数据库"></a>达梦数据库</h3><table>
<thead>
<tr>
<th align="left">参数分类</th>
<th align="left">参数名</th>
<th align="left">参数值</th>
<th align="left">备注</th>
</tr>
</thead>
<tbody><tr>
<td align="left">数据缓存</td>
<td align="left">MEMROY_TARGET、MEMROY_POOL</td>
<td align="left">物理内存90%</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">数据缓存</td>
<td align="left">BUFFER</td>
<td align="left">物理内存60%</td>
<td align="left">数据缓存</td>
</tr>
<tr>
<td align="left">数据缓存</td>
<td align="left">MAX_BUFFER</td>
<td align="left">物理内存70%</td>
<td align="left">最大数据缓存</td>
</tr>
<tr>
<td align="left">监听及连接</td>
<td align="left">max_sessions</td>
<td align="left">根据业务需求设置</td>
<td align="left">一般为业务预估连接数的120%</td>
</tr>
</tbody></table>
<h2 id="SQL优化"><a href="#SQL优化" class="headerlink" title="SQL优化"></a>SQL优化</h2><p>SQL优化很容易理解，就是通过给查询字段添加索引或者改写SQL提高其执行效率，一般而言，SQL编写有以下几个通用的技巧：</p>
<ul>
<li>合理使用索引</li>
</ul>
<p><strong>索引少了查询慢；索引多了占用空间大，执行增删改语句的时候需要动态维护索引，影响性能 选择率高（重复值少）且被where频繁引用需要建立B树索引；一般join列需要建立索引；复杂文档类型查询采用全文索引效率更好；索引的建立要在查询和DML性能之间取得平衡；复合索引创建时要注意基于非前导列查询的情况</strong></p>
<ul>
<li>使用UNION ALL替代UNION</li>
</ul>
<p><strong>UNION ALL的执行效率比UNION高，UNION执行时需要排重；UNION需要对数据进行排序</strong></p>
<ul>
<li>避免select * 写法</li>
</ul>
<p><strong>执行SQL时优化器需要将 * 转成具体的列；每次查询都要回表，不能走覆盖索引。</strong></p>
<ul>
<li>JOIN字段建议建立索引</li>
</ul>
<p><strong>一般JOIN字段都提前加上索引</strong></p>
<ul>
<li>避免复杂SQL语句</li>
</ul>
<p><strong>提升可阅读性；避免慢查询的概率；可以转换成多个短查询，用业务端处理</strong></p>
<ul>
<li>避免where 1=1写法</li>
<li>避免order by rand()类似写法</li>
</ul>
<p><strong>RAND()导致数据列被多次扫描</strong></p>
<h3 id="执行计划"><a href="#执行计划" class="headerlink" title="执行计划"></a>执行计划</h3><p>要想优化SQL必须要会看执行计划，执行计划会告诉你哪些地方效率低，哪里可以需要优化。我们以MYSQL为例，来认识一下执行计划。</p>
<p>通过<code>explain sql</code> 可以查看执行计划，如：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/PxMzT0Oibf4iaicicsWhJbntSpBuNORfVogZmqM1EWticOELy4ia0mpXbDnJJmkiaKtDvHVgwuXCZ3oyicZdo0cVd7onxg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<table>
<thead>
<tr>
<th align="left">字段</th>
<th align="left">解释</th>
</tr>
</thead>
<tbody><tr>
<td align="left">id</td>
<td align="left">每个被独立执行的操作标识，标识对象被操作的顺序，id值越大，先被执行，如果相同，执行顺序从上到下</td>
</tr>
<tr>
<td align="left">select_type</td>
<td align="left">查询中每个select 字句的类型</td>
</tr>
<tr>
<td align="left">table</td>
<td align="left">被操作的对象名称，通常是表名，但有其他格式</td>
</tr>
<tr>
<td align="left">partitions</td>
<td align="left">匹配的分区信息(对于非分区表值为NULL)</td>
</tr>
<tr>
<td align="left">type</td>
<td align="left">连接操作的类型</td>
</tr>
<tr>
<td align="left">possible_keys</td>
<td align="left">可能用到的索引</td>
</tr>
<tr>
<td align="left">key</td>
<td align="left">优化器实际使用的索引(<strong>最重要的列</strong>) 从最好到最差的连接类型为<code>const</code>、<code>eq_reg</code>、<code>ref</code>、<code>range</code>、<code>index</code>和<code>ALL</code>。当出现<code>ALL</code>时表示当前SQL出现了“坏味道”</td>
</tr>
<tr>
<td align="left">key_len</td>
<td align="left">被优化器选定的索引键长度，单位是字节</td>
</tr>
<tr>
<td align="left">ref</td>
<td align="left">表示本行被操作对象的参照对象，无参照对象为NULL</td>
</tr>
<tr>
<td align="left">rows</td>
<td align="left">查询执行所扫描的元组个数（对于innodb，此值为估计值）</td>
</tr>
<tr>
<td align="left">filtered</td>
<td align="left">条件表上数据被过滤的元组个数百分比</td>
</tr>
<tr>
<td align="left">extra</td>
<td align="left">执行计划的重要补充信息，当此列出现<code>Using filesort</code> , <code>Using temporary</code> 字样时就要小心了，很可能SQL语句需要优化</td>
</tr>
</tbody></table>
<h3 id="SQL优化实战"><a href="#SQL优化实战" class="headerlink" title="SQL优化实战"></a>SQL优化实战</h3><p>这里为大家准备了一套SQL优化的综合实战，一步一步带你走一遍完整SQL优化的过程。</p>
<p>在执行优化之前我们需要先认识一下原始表及待优化的SQL。</p>
<ol>
<li>原数据库表结构</li>
</ol>
<figure class="highlight n1ql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> TABLE <span class="symbol">`a`</span></span><br><span class="line">(</span><br><span class="line">    <span class="symbol">`id`</span>          int(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT,</span><br><span class="line">    <span class="symbol">`seller_id`</span>   bigint(<span class="number">20</span>)                                       DEFAULT <span class="literal">NULL</span>,</span><br><span class="line">    <span class="symbol">`seller_name`</span> varchar(<span class="number">100</span>) CHARACTER <span class="keyword">SET</span> utf8 <span class="keyword">COLLATE</span> utf8_bin DEFAULT <span class="literal">NULL</span>,</span><br><span class="line">    <span class="symbol">`gmt_create`</span>  varchar(<span class="number">30</span>)                                      DEFAULT <span class="literal">NULL</span>,</span><br><span class="line">    <span class="keyword">PRIMARY</span> <span class="keyword">KEY</span> (<span class="symbol">`id`</span>)</span><br><span class="line">);</span><br><span class="line"><span class="keyword">CREATE</span> TABLE <span class="symbol">`b`</span></span><br><span class="line">(</span><br><span class="line">    <span class="symbol">`id`</span>          int(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT,</span><br><span class="line">    <span class="symbol">`seller_name`</span> varchar(<span class="number">100</span>) DEFAULT <span class="literal">NULL</span>,</span><br><span class="line">    <span class="symbol">`user_id`</span>     varchar(<span class="number">50</span>)  DEFAULT <span class="literal">NULL</span>,</span><br><span class="line">    <span class="symbol">`user_name`</span>   varchar(<span class="number">100</span>) DEFAULT <span class="literal">NULL</span>,</span><br><span class="line">    <span class="symbol">`sales`</span>       bigint(<span class="number">20</span>)   DEFAULT <span class="literal">NULL</span>,</span><br><span class="line">    <span class="symbol">`gmt_create`</span>  varchar(<span class="number">30</span>)  DEFAULT <span class="literal">NULL</span>,</span><br><span class="line">    <span class="keyword">PRIMARY</span> <span class="keyword">KEY</span> (<span class="symbol">`id`</span>)</span><br><span class="line">);</span><br><span class="line"><span class="keyword">CREATE</span> TABLE <span class="symbol">`c`</span></span><br><span class="line">(</span><br><span class="line">    <span class="symbol">`id`</span>         int(<span class="number">11</span>) <span class="keyword">NOT</span> <span class="literal">NULL</span> AUTO_INCREMENT,</span><br><span class="line">    <span class="symbol">`user_id`</span>    varchar(<span class="number">50</span>)  DEFAULT <span class="literal">NULL</span>,</span><br><span class="line">    <span class="symbol">`order_id`</span>   varchar(<span class="number">100</span>) DEFAULT <span class="literal">NULL</span>,</span><br><span class="line">    <span class="symbol">`state`</span>      bigint(<span class="number">20</span>)   DEFAULT <span class="literal">NULL</span>,</span><br><span class="line">    <span class="symbol">`gmt_create`</span> varchar(<span class="number">30</span>)  DEFAULT <span class="literal">NULL</span>,</span><br><span class="line">    <span class="keyword">PRIMARY</span> <span class="keyword">KEY</span> (<span class="symbol">`id`</span>)</span><br><span class="line">);</span><br></pre></td></tr></table></figure>



<ol>
<li>待优化的SQL（查询当前用户在当前时间前后10个小时的订单情况，并根据订单创建时间升序排列）</li>
</ol>
<figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">select a.seller_id,</span><br><span class="line">       a.seller_name,</span><br><span class="line">       <span class="keyword">b.user_name,</span></span><br><span class="line"><span class="keyword"></span>       c.state</span><br><span class="line">from a,</span><br><span class="line">     <span class="keyword">b,</span></span><br><span class="line"><span class="keyword"></span>     c</span><br><span class="line">where a.seller_name = <span class="keyword">b.seller_name</span></span><br><span class="line"><span class="keyword"></span>  <span class="keyword">and </span><span class="keyword">b.user_id </span>= c.user_id</span><br><span class="line">  <span class="keyword">and </span>c.user_id = <span class="number">17</span></span><br><span class="line">  <span class="keyword">and </span>a.gmt_create</span><br><span class="line">    <span class="keyword">BETWEEN </span>DATE_ADD(NOW(), INTERVAL – <span class="number">600</span> MINUTE)</span><br><span class="line">    <span class="keyword">AND </span>DATE_ADD(NOW(), INTERVAL <span class="number">600</span> MINUTE)</span><br><span class="line"><span class="keyword">order </span><span class="keyword">by </span>a.gmt_create；</span><br></pre></td></tr></table></figure>



<ol>
<li>原表数据量：</li>
</ol>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/PxMzT0Oibf4iaicicsWhJbntSpBuNORfVogZoaX5lLUV2Gibp1ATI99ia0Uyc92Gh29slwOR9NqlXd3AjFQfibC3B5kWA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<ol>
<li>原执行时间</li>
</ol>
<p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/PxMzT0Oibf4iaicicsWhJbntSpBuNORfVogZMkGXYv94jHf69fRH5LDnBw5cCuDXOrKjEtrCSJK5OLKVsV76VGRwRw/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">0.21s，执行速度还挺快</p>
<ol>
<li>原执行计划</li>
</ol>
<p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/PxMzT0Oibf4iaicicsWhJbntSpBuNORfVogZs3xtFkKwUog80SviaOez5vBWrQwvXgFMibjZpAKiaRCFS7sxjV4jObVhA/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">真是糟糕的执行计划。(全表扫描，没有索引；临时表；排序)</p>
<p><strong>初步优化思路：</strong></p>
<ol>
<li>SQL中 where条件字段类型要跟表结构一致，表中<code>user_id</code> 为varchar(50)类型，实际SQL用的int类型，存在隐式转换，也未添加索引。将b和c表<code>user_id</code> 字段改成int类型。</li>
<li>因存在b表和c表关联，将b和c表<code>user_id</code>创建索引</li>
<li>因存在a表和b表关联，将a和b表<code>seller_name</code>字段创建索引</li>
<li>利用复合索引消除临时表和排序</li>
</ol>
<p><strong>初步优化SQL</strong></p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">alter</span> <span class="keyword">table</span> b modify `user_id` <span class="type">int</span>(<span class="number">10</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>;</span><br><span class="line"><span class="keyword">alter</span> <span class="keyword">table</span> c modify `user_id` <span class="type">int</span>(<span class="number">10</span>) <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>;</span><br><span class="line"><span class="keyword">alter</span> <span class="keyword">table</span> c <span class="keyword">add</span> index `idx_user_id`(`user_id`);</span><br><span class="line"><span class="keyword">alter</span> <span class="keyword">table</span> b <span class="keyword">add</span> index `idx_user_id_sell_name`(`user_id`,`seller_name`);</span><br><span class="line"><span class="keyword">alter</span> <span class="keyword">table</span> a <span class="keyword">add</span> index `idx_sellname_gmt_sellid`(`gmt_create`,`seller_name`,`seller_id`);</span><br></pre></td></tr></table></figure>



<p><strong>查看优化后的执行时间</strong></p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/PxMzT0Oibf4iaicicsWhJbntSpBuNORfVogZB3WFry1l3C8ZrM1dBRibGekQyuhicPF73PuZufAdFK8icZxvxZcYWSGZw/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">通过执行计划可以看到，执行时间从0.21s优化成了0.01s，执行时间近乎缩短20倍。</p>
<p><strong>查看优化后的执行计划</strong></p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/PxMzT0Oibf4iaicicsWhJbntSpBuNORfVogZ5WS5TVeo9hicYspiaFhfh8VuXm8KhFqEBwUThibHgG4CMTM8k3x1lIiaJQ/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">执行计划显示从全表扫描优化成了走索引，rows减少，但是此时出现了2个告警。</p>
<p><strong>通过<code>show warning</code>语句 查看告警信息</strong></p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/PxMzT0Oibf4iaicicsWhJbntSpBuNORfVogZbicErgVnxzg5zib5EDfAzIOrresMicBupJqfMrkNAHbQXLH5Nha3dp2yw/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>提示<code>gmt_crteate</code> 的格式不对，mysql进行了隐式转换导致不能使用索引。</p>
<p><strong>继续优化，修改<code>gmtc-create</code>的格式</strong></p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">alter</span> <span class="keyword">table</span> a modify &quot;gmt_create&quot; datetime <span class="keyword">DEFAULT</span> <span class="keyword">NULL</span>;</span><br></pre></td></tr></table></figure>



<p><strong>再次查看执行时间</strong></p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/PxMzT0Oibf4iaicicsWhJbntSpBuNORfVogZbviaibib2lRC2wLsc7V1bhx6jBoKoUL2P2T0utdMiaLPAibxdjpjua2GHqQ/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p><strong>再次查看执行计划</strong></p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/PxMzT0Oibf4iaicicsWhJbntSpBuNORfVogZq4MvsGjiahxaQWgUep0QZ01iccsTCqZeQAxS9xpwN8dSeX0yKSEAuQkg/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>至此，我们的优化过程结束，结果非常完美。</p>
<h3 id="SQL优化小结"><a href="#SQL优化小结" class="headerlink" title="SQL优化小结"></a>SQL优化小结</h3><p>这里给大家总结一下SQL优化的套路：</p>
<ol>
<li>查看执行计划 <code>explain sql</code></li>
<li>如果有告警信息，查看告警信息 <code>show warnings;</code></li>
<li>查看SQL涉及的表结构和索引信息</li>
<li>根据执行计划，思考可能的优化点</li>
<li>按照可能的优化点执行表结构变更、增加索引、SQL改写等操作</li>
<li>查看优化后的执行时间和执行计划</li>
<li>如果优化效果不明显，重复第四步操作</li>
</ol>

      
    </div>
<div>
  
</div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wan-lei8.gitee.io/2022/01/24/%E7%B4%A2%E5%BC%95%E4%BC%98%E5%8C%96/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员西桐">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2022/01/24/%E7%B4%A2%E5%BC%95%E4%BC%98%E5%8C%96/" class="post-title-link" itemprop="url">索引优化</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-01-24 16:38:13 / 修改时间：16:38:42" itemprop="dateCreated datePublished" datetime="2022-01-24T16:38:13+08:00">2022-01-24</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h2 id="Mysql索引"><a href="#Mysql索引" class="headerlink" title="Mysql索引"></a>Mysql索引</h2><p>Mysql的索引是一种加快查询速度的数据结构，索引就好比书的目录一样能够快速的定位你要查找的位置。</p>
<p>Mysql的索引底层是使用B+树的数据结构进行实现，结构如下图所示：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPOEiaCXvzESCWNibctG2icZBE2WDwybNZdREF1KKhylLalkibsONGSA3icic4Q/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">索引的一个数据页的大小是16kb，从磁盘加载到内存中是以数据页的大小为单位进行加载，然后供查询操作进行查询，若是查询的数据不在内存中，才会从磁盘中再次加载到内存中。</p>
<p>索引的实现有很多，比如hash。hash是以key-value的形式进行存储，适合于等值查询的场景，查询的时间复杂度为O(1)，因为hash储存并不是有序的。</p>
<p>所以，对于范围查询就可能要遍历所有数据进行查询，而且不同值的计算还会出现hash冲突，所以hash并不适合于做Mysql的索引。</p>
<p>有序数组在等值查询和范围查询性能都是非常好的，那为什么又不用有序数组作为索引呢？因为对于数组而言作为索引更新的成本太高，新增数据要把后面的数据都往后移一位，所以也不采用有序数组作为索引的底层实现。</p>
<p>最后二叉树，主要是因为二叉树只有二叉，一个节点存储的数据量非常有限，需要频繁的随机IO读写磁盘，若是数据量大的情况下二叉的树高太高，严重影响性能，所以也不采用二叉树进行实现。</p>
<p>而B+树是多叉树，一个数据页的大小是16kb，在1-3的树高就能存储10亿级以上的数据，也就是只要访问磁盘1-3次就足够了，并且B+树的叶子结点上一个叶子结点有指针指向下一个叶子结点，便于范围查询：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPO8CmxKpzIbky5Uez5hhCicyhrXR8tZDX8JAIPMicVK3TsDXs0ErV2eia0A/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<h3 id="种类的索引"><a href="#种类的索引" class="headerlink" title="种类的索引"></a>种类的索引</h3><p>索引从数据结构进行划分的分为：<strong>B+树索引、hash索引、R-Tree索引、FULLTEXT索引</strong>。</p>
<p>索引从物理存储的角度划分为：<strong>聚族索引和非聚族索引</strong>。</p>
<p>从逻辑的角度分为：<strong>主键索引、普通索引、唯一索引、联合索引以及空间索引</strong>。</p>
<h2 id="什么是回表"><a href="#什么是回表" class="headerlink" title="什么是回表"></a>什么是回表</h2><p>再详细了解什么事回表之前，我们先来详细的深入了解一下什么是InnoDB的索引存储形式，InnoDB的主键索引存储形式是聚族索引，索引与数据都在一起：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPOTwJRctD9VC5kQLCW0EQ6fXzs5WaO1dv1x7O5SJhoV5sA3GeXj4GibTQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">InnoDB的主键索引中叶子结点并不是存储行指针，而是存储行数据，二级索引中MyISAM也是一样的存储方式，InnoDB的二级索引的叶子结点则是存储当前索引值以及对应的主键索引值。</p>
<p>InnoDB的二级索引带来的好处就是减少了由于数据移动或者数据页分列导致行数据的地址变了而带来的维护二级索引的性能开销，因为InnoDB的二级索引不需要更新行指针：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPOtTS6Nl7nB24icD1GypIYOQjAhmBxfjLv4Yb0NCjx3msGHice56LLHH5A/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>上面说到InnoDB引擎的主键索引存储的是行数据，二级索引的叶子结点存储的是索引数据以及对应的主键，所以回表就是根据索引进行条件查询，回到主键索引树进行搜索的过程：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPOmiccvicv6Emql9KQHpJKHdDgOrFLJa0zEbeF7UogbuAss07EhTjbbibgQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>因为查询还要回表一次，再次查询主键索引树，所以实际中应该尽量避免回表的产生。</p>
<h3 id="解决回表"><a href="#解决回表" class="headerlink" title="解决回表"></a>解决回表</h3><p>解决回表问题可以建立联合索引进行索引覆盖，如图所示根据name字段查询用户的name和sex属性出现了回表问题：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPOmiccvicv6Emql9KQHpJKHdDgOrFLJa0zEbeF7UogbuAss07EhTjbbibgQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">那么我们可以建立下面这个联合索引来解决：</p>
<figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">create</span> <span class="keyword">table</span> <span class="keyword">user</span> (</span><br><span class="line"> id <span class="type">int</span> <span class="keyword">primary key</span>,</span><br><span class="line"> <span class="type">name</span> <span class="type">varchar</span>(<span class="number">20</span>),</span><br><span class="line"> sex <span class="type">varchar</span>(<span class="number">5</span>),</span><br><span class="line"> <span class="keyword">index</span>(<span class="type">name</span>, sex)</span><br><span class="line">) engine = innodb;</span><br></pre></td></tr></table></figure>

<p>建立了如上所示的index(name,sex)联合索引，在二级索引的叶子结点的位置就会同时也出现sex字段的值，因为能够获取到要查询的所有字段，因为就不用再回表查询一次。</p>
<h2 id="最左前缀原则"><a href="#最左前缀原则" class="headerlink" title="最左前缀原则"></a>最左前缀原则</h2><p>最左前缀原则可以是联合索引的的最左N个字段，也可以是字符串索引的最左的M个字符。举个例子，假如现在有一个表的原始数据如下所示：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPOIsQbKUX5FeoS41iaen93ib21rLibbia8iaWmwaIicAWtvf6w2kp8Via9YnKNw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>并根据col3 ，col2的顺序建立联合索引，此时联合索引树结构如图下所示：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPOqicjTkb53FdQcgtRhUwa8969O06AiaapyWXduPkUBOqiaibPcf7pkibkvFg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>叶子结点中首先会根据col3的字符进行排序，若是col3相等，在col3相等的值里面再对col2进行排序，假如我们要查询where col3 like ‘Eri%’，就可以快速的定位查询到Eric。</p>
<p>若是查询条件为where col3 like ‘%se’，前面的字符不确定，表示任意字符都可以，这样就可以导致全表扫描进行字符的比较，就会使索引失效。</p>
<h2 id="调优案例一"><a href="#调优案例一" class="headerlink" title="调优案例一"></a>调优案例一</h2><p>其中第一个案例新人写了一个这样的sql，由于业务的原因就不粘贴全部sql，其中sql的条件如下所示<strong>WHERE ( STATUS = ‘1’ AND shop_code = ‘XXX’ )  GROUP BY act_id</strong>。</p>
<p>并且他在表中建立的这样的一个索引<strong>idx_status_shop_code</strong>，当时看到就吐血一地。</p>
<p>我给新人提出建议是把shop_code为’’空字符串的（数据库默认值）是设为一个特殊的00000这样的类型，不要把商店的shop_code默认值设置为空字符串。</p>
<p>并且，索引中shop_code字段放在前面，建<strong>idx_shop_code_status_act_id</strong>索引。</p>
<p><strong>因为一般状态值status只有0和1，区分度不大，而shop_code的区分度大，在执行where条件筛选的时候，区分度大的放在前面，第一层过滤的时候就能过滤掉大部分行数，减少扫描的行数，提高效率。</strong></p>
<p>并且将act_id，和store_code也加入其中，sql中涉及分组（group by）操作，这样就能避免filesort排序，因为索引本来就是有序的：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPOYcjjEC0BicDFljIIG4Gj0IsLVmR1NePLQdZpcPDCbDSRTGoibs6BgSOg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>并且从他的sql中可以看到他只要返回act_id，而实际中只用到了act_id，所以将act_id也加入索引中就可以避免回表的操作，所以再索引中最后加入act_id有两大好处：<strong>避免回表以及避免filesort排序</strong>。</p>
<p>因为写sql的不良习惯造成回表操作，平时也没有注意建立索引的一些原则，以及理解索引的一些原理，所以新人对于一些优化的理解还有要一步一步的指导，毕竟自己也是从新人过来的。</p>
<p>对于索引的顺序的建立，以及出现filesort的解决方案在阿里的开发手册中也有提到：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPOqJNdSVQY9KyGbBL6nAYBu7PbT700vdwlwYiaicotcFv7ojRMia6U9qtbQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>order by和group by都可以利用索引的有序性。</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPOKrud7ezObIjoib7mDepOia3DHFXxic5vvf8reHzSzxUx5GzCulLdKM0Mw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>说真的这本开发手册还是非常好用的，里面很多经验总结，慢慢的遇到场景就能够瞬间顿悟，毕竟是众多阿里人的开发经验的结晶。</p>
<h2 id="调优案例二"><a href="#调优案例二" class="headerlink" title="调优案例二"></a>调优案例二</h2><p>第二个案例是关于字符串的，新人接到一个需求需要比较电话，但是一般电话在数据库中都会加密md5。</p>
<p>所以，新人为了提高查询的效率新建KEY <code>idx_mobile_md5_type</code> (<code>mobile_md5</code>,<code>type</code>)使用md5全字段建立索引。</p>
<p>我是建议他使用<strong>select count(distinct left(mobile_md5, 5))/count(*) from XXX.users</strong>查找最大的区分度：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPOsNyscL1cV1R6Rxo26ITpQKBnmfldXrB7DhtY3rGd7s8Tia5flVuNbdw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>在实际中当md5值长度为5以及大于5的长度都不变了：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPOgTtIfy6TicsTHVOdTialouJUbeZ5ZKwvqZk1icflHzLZFLYVcvONcDPpA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>实际情况只要前五个字符就能达到80%的区分度，并且再加字段长度区分度也不变，所以个人提出只要建立前五个字符的索引即可，可以大大节约空间。</p>
<p>这个在阿里的开发手册也有提到，其实一般来说达到90%的区分度是比较好的，区分度越大，就类似于越趋向于唯一索引，过滤的行数就越多：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/IJUXwBNpKlg5vibfMDibOVCic39xwMJylPO37ribjawQYbBaMt2XMxnUMRzWeA3ibLJRS73zjyVLBRO6RTK8eQRvY8A/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<h2 id="调优案例三"><a href="#调优案例三" class="headerlink" title="调优案例三"></a>调优案例三</h2><p>最后一个字符串的案例就是userId，这个userId使用有20位的长度的字符串左右，有点类似于身份证号码，大家都知道身份证号码的前多少位是基本一样的，区别大的在后面的几位（具体几位没去了解过）。</p>
<p>我们这边的场景也是一样，userId前10位左右基本都是一样，反而只有后面的几位区别度高达90%以上。</p>
<p>所以，建议新人建立userId的反转之后的前几位索引即可，区别度可以通过：<strong>select count(distinct left(REVERSE(userId), 7))/count(*) as ‘区分度’ from XXX.users;</strong></p>
<p>具体sql如下的sql：<strong>select u.city_code from XXX.city_role_user u where  role_key = ‘XXX’ and uc_id = ‘XXX’ and status = 1;</strong></p>
<p>这个sql有两个问题，一个是把区分度不大的role_key放在前面，因为一般角色key在PC端只有几种，区别度很小；另一个就是前面说的uc_id字符串问题。</p>
<p>我是建议把where条件的条件uc_id放在前面，建立索引也是如此，并且uc_id是由20位的数字组成，前面的10位左右都是一样的，只有后面的几位区分度才大。</p>
<p>所以个人也建议通过查询区分度，并且建立翻转字符串后的索引来达到节省空间，并且还可以提升查询效率，最后就是city_code也加入索引中建立联合索引就可以避免回表操作。</p>
<p>所以，这就要sql优化的关键点有三个：<strong>区分度大的放在前面、字符串减少长度、避免回表</strong>。</p>
<h2 id="其它的code-review"><a href="#其它的code-review" class="headerlink" title="其它的code review"></a>其它的code review</h2><p>通过code review新人的代码，还发现一些问题，就是不遵循接口的单一原则，比较喜欢写通用的接口，一个接口多个场景使用，通常使用select * 返回数据，对于一些where条件的查询需要大量的回表操作，但是一些接口中只需要用到其中select 回来的一个字段，所以导致慢sql，慢接口的产生。</p>
<p>并且，在实际的编码中主要是面向于实现，对于一些整体的模块没有把控，类似于一些可以使用到<strong>策略模式、建造者模式</strong>等设计模式的，都没有使用，代码的扩展性比较差。</p>
<p>还要在代码中大量的使用Java 8的stream流操作，代码的可读性差，对于stream流其实可以用来并行流处理还是挺高效的，因为stream流的底层使用到了Fork/Join。</p>
<p>在服务器配置允许的条件下，使用如下代码，数据量大的时候是可以有效率提升的，下面引用redspider的一个案例：</p>
<figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">public <span class="keyword">class</span> StreamParallelDemo &#123;</span><br><span class="line">    public static void main(String<span class="literal">[]</span> args) &#123;</span><br><span class="line">        <span class="module-access"><span class="module"><span class="identifier">System</span>.</span></span>out.println(<span class="module-access"><span class="module"><span class="identifier">String</span>.</span></span>format(<span class="string">&quot;本计算机的核数：%d&quot;</span>, <span class="module-access"><span class="module"><span class="identifier">Runtime</span>.</span></span>get<span class="constructor">Runtime()</span>.available<span class="constructor">Processors()</span>));</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 产生100w个随机数(1 ~ 100)，组成列表</span></span><br><span class="line">        Random random = <span class="keyword">new</span> <span class="constructor">Random()</span>;</span><br><span class="line">        List&lt;Integer&gt; <span class="built_in">list</span> = <span class="keyword">new</span> ArrayList&lt;&gt;(<span class="number">1000_0000</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="built_in">int</span> i = <span class="number">0</span>; i &lt; <span class="number">1000_0000</span>; i++) &#123;</span><br><span class="line">            <span class="built_in">list</span>.add(random.next<span class="constructor">Int(100)</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        long prevTime = get<span class="constructor">CurrentTime()</span>;</span><br><span class="line">        <span class="built_in">list</span>.stream<span class="literal">()</span>.reduce((a, b) -&gt; a + b).<span class="keyword">if</span><span class="constructor">Present(System.<span class="params">out</span>::<span class="params">println</span>)</span>;</span><br><span class="line">        <span class="module-access"><span class="module"><span class="identifier">System</span>.</span></span>out.println(<span class="module-access"><span class="module"><span class="identifier">String</span>.</span></span>format(<span class="string">&quot;单线程计算耗时：%d&quot;</span>, get<span class="constructor">CurrentTime()</span> - prevTime));</span><br><span class="line"></span><br><span class="line">        prevTime = get<span class="constructor">CurrentTime()</span>;</span><br><span class="line">        <span class="built_in">list</span>.stream<span class="literal">()</span>.parallel<span class="literal">()</span>.reduce((a, b) -&gt; a + b).<span class="keyword">if</span><span class="constructor">Present(System.<span class="params">out</span>::<span class="params">println</span>)</span>;</span><br><span class="line">        <span class="module-access"><span class="module"><span class="identifier">System</span>.</span></span>out.println(<span class="module-access"><span class="module"><span class="identifier">String</span>.</span></span>format(<span class="string">&quot;多线程计算耗时：%d&quot;</span>, get<span class="constructor">CurrentTime()</span> - prevTime));</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> static long get<span class="constructor">CurrentTime()</span> &#123;</span><br><span class="line">        return <span class="module-access"><span class="module"><span class="identifier">System</span>.</span></span>current<span class="constructor">TimeMillis()</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>一路code review，发现还是挺多问题，也是非常基础的东西，这里就顺手做了个记录，不过也情有可原，毕竟是新人，只能慢慢的指导，一行代码一行代码的手把手教。</p>

      
    </div>
<div>
  
</div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wan-lei8.gitee.io/2022/01/24/%E7%BB%99%E4%BD%A0%E7%9A%84Java%E7%A8%8B%E5%BA%8F%E6%8B%8D%E4%B8%AA%E7%89%87%E5%AD%90%E5%90%A7-jstack%E5%91%BD%E4%BB%A4%E8%A7%A3%E6%9E%90/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员西桐">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2022/01/24/%E7%BB%99%E4%BD%A0%E7%9A%84Java%E7%A8%8B%E5%BA%8F%E6%8B%8D%E4%B8%AA%E7%89%87%E5%AD%90%E5%90%A7-jstack%E5%91%BD%E4%BB%A4%E8%A7%A3%E6%9E%90/" class="post-title-link" itemprop="url">给你的Java程序拍个片子吧:jstack命令解析</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-01-24 15:59:09 / 修改时间：16:04:19" itemprop="dateCreated datePublished" datetime="2022-01-24T15:59:09+08:00">2022-01-24</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>如果有一天，你的Java程序长时间停顿，也许是它病了，需要用jstack拍个片子分析分析，才能诊断具体什么病症，是死锁综合征，还是死循环等其他病症，本文我们一起来学习jstack命令~</p>
<ul>
<li>jstack 的功能</li>
<li>jstack用法</li>
<li>线程状态等基础回顾</li>
<li>实战案例1：jstack 分析死锁</li>
<li>实战案例2：jstack 分析CPU 过高</li>
</ul>
<h2 id="jstack-的功能"><a href="#jstack-的功能" class="headerlink" title="jstack 的功能"></a>jstack 的功能</h2><p>jstack是JVM自带的Java堆栈跟踪工具，它用于打印出给定的java进程ID、core file、远程调试服务的Java堆栈信息.</p>
<figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">jstack </span>prints <span class="keyword">Java </span>stack traces of <span class="keyword">Java </span>threads for a given <span class="keyword">Java </span>process <span class="keyword">orcore </span>file <span class="keyword">or </span>a remote <span class="built_in">debug</span> server. </span><br></pre></td></tr></table></figure>

<blockquote>
<ul>
<li>jstack命令用于生成虚拟机当前时刻的线程快照。</li>
<li>线程快照是当前虚拟机内每一条线程正在执行的方法堆栈的集合，生成线程快照的主要目的是定位线程出现长时间停顿的原因， 如线程间死锁、死循环、请求外部资源导致的长时间等待等问题。</li>
<li>线程出现停顿的时候通过jstack来查看各个线程的调用堆栈，就可以知道没有响应的线程到底在后台做什么事情，或者等待什么资源。</li>
<li>如果java程序崩溃生成core文件，jstack工具可以用来获得core文件的java stack和native stack的信息，从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。</li>
<li>另外，jstack工具还可以附属到正在运行的java程序中，看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态，jstack是非常有用的。</li>
</ul>
</blockquote>
<h2 id="jstack用法"><a href="#jstack用法" class="headerlink" title="jstack用法"></a>jstack用法</h2><p><strong>jstack 命令格式如下</strong></p>
<figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jstack <span class="selector-attr">[ option ]</span> pidjstack <span class="selector-attr">[ option ]</span> executable corejstack <span class="selector-attr">[ option ]</span> <span class="selector-attr">[server-id@]</span>remote-hostname-or-IP</span><br></pre></td></tr></table></figure>

<ul>
<li>executable Java executable from which the core dump was produced.(可能是产生core dump的java可执行程序)</li>
<li>core 将被打印信息的core dump文件</li>
<li>remote-hostname-or-IP 远程debug服务的主机名或ip</li>
<li>server-id 唯一id,假如一台主机上多个远程debug服务</li>
</ul>
<p><strong>最常用的是</strong></p>
<figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jstack [option] &lt;pid&gt;  <span class="regexp">//</span> 打印某个进程的堆栈信息</span><br></pre></td></tr></table></figure>

<p><strong>option参数说明如下：</strong></p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPdO0OdCJ41EjGxjBkXL1gHndsAkwWibqv50APmueZWwJKaP67nz48tng/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<table>
<thead>
<tr>
<th align="left">选项</th>
<th align="left">作用</th>
</tr>
</thead>
<tbody><tr>
<td align="left">-F</td>
<td align="left">当正常输出的请求不被响应时，强制输出线程堆栈</td>
</tr>
<tr>
<td align="left">-m</td>
<td align="left">如果调用到本地方法的话，可以显示C/C++的堆栈</td>
</tr>
<tr>
<td align="left">-l</td>
<td align="left">除堆栈外，显示关于锁的附加信息，在发生死锁时可以用jstack -l pid来观察锁持有情况</td>
</tr>
</tbody></table>
<h2 id="线程状态等基础回顾"><a href="#线程状态等基础回顾" class="headerlink" title="线程状态等基础回顾"></a>线程状态等基础回顾</h2><h3 id="线程状态简介"><a href="#线程状态简介" class="headerlink" title="线程状态简介"></a>线程状态简介</h3><p>jstack用于生成线程快照的，我们分析线程的情况，需要复习一下线程状态吧，拿小凳子坐好，复习一下啦~<img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPYicAQhWgxXRvuFzZz0gXib7JnibGDP9jrPyvqTDo6ftoSwsNC1YvZ75ZA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p><strong>Java语言定义了6种线程池状态：</strong></p>
<ul>
<li>New：创建后尚未启动的线程处于这种状态，不会出现在Dump中。</li>
<li>RUNNABLE：包括Running和Ready。线程开启start（）方法，会进入该状态，在虚拟机内执行的。</li>
<li>Waiting：无限的等待另一个线程的特定操作。</li>
<li>Timed Waiting：有时限的等待另一个线程的特定操作。</li>
<li>阻塞（Blocked）：在程序等待进入同步区域的时候，线程将进入这种状态，在等待监视器锁。</li>
<li>结束（Terminated）：已终止线程的线程状态，线程已经结束执行。</li>
</ul>
<p><strong>Dump文件的线程状态一般其实就以下3种：</strong></p>
<ul>
<li>RUNNABLE，线程处于执行中</li>
<li>BLOCKED，线程被阻塞</li>
<li>WAITING，线程正在等待</li>
</ul>
<h3 id="Monitor-监视锁"><a href="#Monitor-监视锁" class="headerlink" title="Monitor 监视锁"></a>Monitor 监视锁</h3><p>因为Java程序一般都是多线程运行的，Java多线程跟监视锁环环相扣，所以我们分析线程状态时，也需要回顾一下Monitor监视锁知识。</p>
<p>有关于线程同步关键字Synchronized与监视锁的爱恨情仇，有兴趣的伙伴可以看一下我这篇文章<a target="_blank" rel="noopener" href="http://mp.weixin.qq.com/s?__biz=MzIwOTE2MzU4NA==&mid=2247483711&idx=1&sn=884f5c0f3e286226e35341509a0db546&chksm=97794510a00ecc06a5e3a77ea60b9476e51d1b6025cc1e86e0a9ab22ff36aa76666e3e400039&scene=21#wechat_redirect">Synchronized解析——如果你愿意一层一层剥开我的心</a></p>
<p>Monitor的工作原理图如下：</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPFCFMejdKAPicgfkAx6Eaa2CvBOSFAwQt6HZaxUAeP88HCHANoF3Lfww/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<ul>
<li>线程想要获取monitor,首先会进入Entry Set队列，它是Waiting Thread，线程状态是Waiting for monitor entry。</li>
<li>当某个线程成功获取对象的monitor后,进入Owner区域，它就是Active Thread。</li>
<li>如果线程调用了wait()方法，则会进入Wait Set队列，它会释放monitor锁，它也是Waiting Thread，线程状态in Object.wait()</li>
<li>如果其他线程调用 notify() / notifyAll() ，会唤醒Wait Set中的某个线程，该线程再次尝试获取monitor锁，成功即进入Owner区域。</li>
</ul>
<h3 id="Dump-文件分析关注重点"><a href="#Dump-文件分析关注重点" class="headerlink" title="Dump 文件分析关注重点"></a>Dump 文件分析关注重点</h3><ul>
<li>runnable，线程处于执行中</li>
<li>deadlock，死锁（重点关注）</li>
<li>blocked，线程被阻塞 （重点关注）</li>
<li>Parked，停止</li>
<li>locked，对象加锁</li>
<li>waiting，线程正在等待</li>
<li>waiting to lock 等待上锁</li>
<li>Object.wait()，对象等待中</li>
<li>waiting for monitor entry 等待获取监视器（重点关注）</li>
<li>Waiting on condition，等待资源（重点关注），最常见的情况是线程在等待网络的读写</li>
</ul>
<h2 id="实战案例1：jstack-分析死锁问题"><a href="#实战案例1：jstack-分析死锁问题" class="headerlink" title="实战案例1：jstack 分析死锁问题"></a>实战案例1：jstack 分析死锁问题</h2><ul>
<li>什么是死锁？</li>
<li>如何用jstack排查死锁？</li>
</ul>
<h3 id="什么是死锁？"><a href="#什么是死锁？" class="headerlink" title="什么是死锁？"></a>什么是死锁？</h3><p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPk8pUnYFqFdmCswT5zh8P5lkC6Fuxykw7gyaXSrI3n5ia8DJl5suXMcQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>死锁是指两个或两个以上的线程在执行过程中，因争夺资源而造成的一种互相等待的现象，若无外力作用，它们都将无法进行下去。</p>
<h3 id="如何用如何用jstack排查死锁问题"><a href="#如何用如何用jstack排查死锁问题" class="headerlink" title="如何用如何用jstack排查死锁问题"></a>如何用如何用jstack排查死锁问题</h3><p>先来看一段会产生死锁的Java程序，源码如下：</p>
<figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** * Java 死锁demo */</span>public <span class="keyword">class</span> DeathLockTest &#123;    <span class="keyword">private</span> static Lock lock1 = <span class="keyword">new</span> <span class="constructor">ReentrantLock()</span>;    <span class="keyword">private</span> static Lock lock2 = <span class="keyword">new</span> <span class="constructor">ReentrantLock()</span>;</span><br><span class="line">    public static void death<span class="constructor">Lock()</span> &#123;        Thread t1 = <span class="keyword">new</span> <span class="constructor">Thread()</span> &#123;            @Override            public void run<span class="literal">()</span> &#123;                <span class="keyword">try</span> &#123;                    lock1.lock<span class="literal">()</span>;                    <span class="module-access"><span class="module"><span class="identifier">System</span>.</span></span>out.println(<span class="module-access"><span class="module"><span class="identifier">Thread</span>.</span></span>current<span class="constructor">Thread()</span>.get<span class="constructor">Name()</span> + <span class="string">&quot; get the lock1&quot;</span>);                    <span class="module-access"><span class="module"><span class="identifier">Thread</span>.</span></span>sleep(<span class="number">1000</span>);                    lock2.lock<span class="literal">()</span>;                    <span class="module-access"><span class="module"><span class="identifier">System</span>.</span></span>out.println(<span class="module-access"><span class="module"><span class="identifier">Thread</span>.</span></span>current<span class="constructor">Thread()</span>.get<span class="constructor">Name()</span> + <span class="string">&quot; get the lock2&quot;</span>);                &#125; catch (InterruptedException e) &#123;                    e.print<span class="constructor">StackTrace()</span>;                &#125;            &#125;        &#125;;        Thread t2 = <span class="keyword">new</span> <span class="constructor">Thread()</span> &#123;            @Override            public void run<span class="literal">()</span> &#123;                <span class="keyword">try</span> &#123;                    lock2.lock<span class="literal">()</span>;                    <span class="module-access"><span class="module"><span class="identifier">System</span>.</span></span>out.println(<span class="module-access"><span class="module"><span class="identifier">Thread</span>.</span></span>current<span class="constructor">Thread()</span>.get<span class="constructor">Name()</span> + <span class="string">&quot; get the lock2&quot;</span>);                    <span class="module-access"><span class="module"><span class="identifier">Thread</span>.</span></span>sleep(<span class="number">1000</span>);                    lock1.lock<span class="literal">()</span>;                    <span class="module-access"><span class="module"><span class="identifier">System</span>.</span></span>out.println(<span class="module-access"><span class="module"><span class="identifier">Thread</span>.</span></span>current<span class="constructor">Thread()</span>.get<span class="constructor">Name()</span> + <span class="string">&quot; get the lock1&quot;</span>);                &#125; catch (InterruptedException e) &#123;                    e.print<span class="constructor">StackTrace()</span>;                &#125;            &#125;        &#125;;        <span class="comment">//设置线程名字，方便分析堆栈信息        t1.setName(&quot;mythread-jay&quot;);        t2.setName(&quot;mythread-tianluo&quot;);        t1.start();        t2.start();    &#125;    public static void main(String[] args) &#123;        deathLock();    &#125;&#125;</span></span><br></pre></td></tr></table></figure>

<p>运行结果：<img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPtMYltl8xic4Micls7svoCiabdb01VFyVFj4geYNCRbnr207sup2M4x7XA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">显然，线程jay和线程tianluo都是只执行到一半，就陷入了阻塞等待状态~</p>
<h3 id="jstack排查Java死锁步骤"><a href="#jstack排查Java死锁步骤" class="headerlink" title="jstack排查Java死锁步骤"></a>jstack排查Java死锁步骤</h3><ul>
<li>在终端中输入jsp查看当前运行的java程序</li>
<li>使用 jstack -l pid 查看线程堆栈信息</li>
<li>分析堆栈信息</li>
</ul>
<h3 id="在终端中输入jsp查看当前运行的java程序"><a href="#在终端中输入jsp查看当前运行的java程序" class="headerlink" title="在终端中输入jsp查看当前运行的java程序"></a>在终端中输入jsp查看当前运行的java程序</h3><p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPnhjj4m4DV6CxCrlnt7butZcqf5XiaBnySDJQgp8WVF2DqTyDKnNJNcA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">通过使用 jps 命令获取需要监控的进程的pid，我们找到了 <code>23780DeathLockTest</code></p>
<h3 id="使用-jstack-l-pid-查看线程堆栈信息"><a href="#使用-jstack-l-pid-查看线程堆栈信息" class="headerlink" title="使用 jstack -l pid 查看线程堆栈信息"></a>使用 jstack -l pid 查看线程堆栈信息</h3><p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPaibqrGRzVD5icJztot8fZiaaPf26E10L45Sicicn8PQXmlSAsoDBUibvnVfA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">由上图，可以清晰看到<strong>死锁</strong>信息：</p>
<ul>
<li>mythread-tianluo 等待这个锁 “0x00000000d61ae3a0”，这个锁是由mythread-jay线程持有。</li>
<li>mythread-jay线程等待这个锁“0x00000000d61ae3d0”,这个锁是由mythread-tianluo 线程持有。</li>
</ul>
<h3 id="还原死锁真相"><a href="#还原死锁真相" class="headerlink" title="还原死锁真相"></a>还原死锁真相</h3><p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPtSwLosvndDMcicsDFjVgUPZYZhSB63oVv3NbAQA2ImsjZWToq5zFJ5g/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"><strong>“mythread-tianluo”线程堆栈信息分析如下：</strong></p>
<ul>
<li>mythread-tianluo的线程处于等待（waiting）状态，持有“0x00000000d61ae3d0”锁，等待“0x00000000d61ae3a0”的锁</li>
</ul>
<p><strong>“mythread-jay”线程堆栈信息分析如下：</strong></p>
<ul>
<li>mythread-tianluo的线程处于等待（waiting）状态，持有“0x00000000d61ae3a0”锁，等待“0x00000000d61ae3d0”的锁</li>
</ul>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPy2RBEn8gib48zib7X7s1460zktKXwMuJd61vcp9oYvePnqbmOw9nEZIA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<h2 id="实战案例2：jstack-分析CPU过高问题"><a href="#实战案例2：jstack-分析CPU过高问题" class="headerlink" title="实战案例2：jstack 分析CPU过高问题"></a>实战案例2：jstack 分析CPU过高问题</h2><p>来个导致CPU过高的demo程序，一个死循环，哈哈~</p>
<figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** * 有个导致CPU过高程序的demo，死循环 */</span><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JstackCase</span> &#123;</span></span><br><span class="line">     <span class="keyword">private</span> <span class="keyword">static</span> ExecutorService executorService = Executors.<span class="built_in">newFixedThreadPool</span>(<span class="number">5</span>);</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(<span class="keyword">String</span>[] args)</span> </span>&#123;</span><br><span class="line">        <span class="built_in">Task</span> task1 = <span class="keyword">new</span> <span class="built_in"><span class="built_in">Task</span></span>();        <span class="built_in">Task</span> task2 = <span class="keyword">new</span> <span class="built_in"><span class="built_in">Task</span></span>();        executorService.<span class="built_in">execute</span>(task1);        executorService.<span class="built_in">execute</span>(task2);    &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> Object lock = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br><span class="line">    <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">Task</span> <span class="title">implements</span> <span class="title">Runnable</span>&#123;</span></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;            <span class="built_in">synchronized</span> (lock)&#123;                <span class="keyword">long</span> sum = <span class="number">0L</span>;                <span class="keyword">while</span> (<span class="literal">true</span>)&#123;                    sum += <span class="number">1</span>;                &#125;            &#125;        &#125;    &#125;&#125;</span><br></pre></td></tr></table></figure>

<h3 id="jstack-分析CPU过高步骤"><a href="#jstack-分析CPU过高步骤" class="headerlink" title="jstack 分析CPU过高步骤"></a>jstack 分析CPU过高步骤</h3><ul>
<li>top</li>
<li>top -Hp pid</li>
<li>jstack pid</li>
<li> jstack -l [PID] &gt;/tmp/log.txt</li>
<li>分析堆栈信息</li>
</ul>
<h3 id="1-top"><a href="#1-top" class="headerlink" title="1.top"></a>1.top</h3><p>在服务器上，我们可以通过top命令查看各个进程的cpu使用情况，它默认是按cpu使用率由高到低排序的<img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPCFtAkz3cCs4Obexwlym6IjyOnVEVXTdUeWddpicOfBA4jxlbd64uiaqQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>由上图中，我们可以找出pid为21340的java进程，它占用了最高的cpu资源，凶手就是它，哈哈！</p>
<h3 id="2-top-Hp-pid"><a href="#2-top-Hp-pid" class="headerlink" title="2. top -Hp pid"></a>2. top -Hp pid</h3><p>通过top -Hp 21340可以查看该进程下，各个线程的cpu使用情况，如下：<img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPLVLCFic60S0gDu1esRjE6bXUhj9qY7ibAiaBZQ75PekFApLASxPSERJ1w/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>可以发现pid为21350的线程，CPU资源占用最高<del>，嘻嘻，小本本把它记下来，接下来拿jstack给它拍片子</del></p>
<h3 id="3-jstack-pid"><a href="#3-jstack-pid" class="headerlink" title="3. jstack pid"></a>3. jstack pid</h3><p>通过top命令定位到cpu占用率较高的线程之后，接着使用jstack pid命令来查看当前java进程的堆栈状态， <code>jstack21350</code>后，内容如下：<img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPEEl5CKOicgAdib0ZzicOmG7TLIEicUjNQwyhtggFNmGESpNBwLduZj205w/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<h3 id="4-jstack-l-PID-gt-tmp-log-txt"><a href="#4-jstack-l-PID-gt-tmp-log-txt" class="headerlink" title="4. jstack -l [PID] &gt;/tmp/log.txt"></a>4. jstack -l [PID] &gt;/tmp/log.txt</h3><p>其实，前3个步骤，堆栈信息已经出来啦。但是一般在生成环境，我们可以把这些堆栈信息打到一个文件里，再回头仔细分析哦~</p>
<h3 id="5-分析堆栈信息"><a href="#5-分析堆栈信息" class="headerlink" title="5. 分析堆栈信息"></a>5. 分析堆栈信息</h3><p>我们把占用cpu资源较高的线程pid（本例子是21350），将该pid转成16进制的值</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPicCYKoGqicrzuJOs5HpyWWqVxg7PzQ8q71LQmA0RpVYrTPZE6HaJBQLw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片">在thread dump中，每个线程都有一个nid，我们找到对应的nid（5366），发现一直在跑（24行）</p>
<p><img src="https://mmbiz.qpic.cn/mmbiz_png/sMmr4XOCBzGbd31otyRCFG858WqITjsPEEl5CKOicgAdib0ZzicOmG7TLIEicUjNQwyhtggFNmGESpNBwLduZj205w/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片"></p>
<p>这个时候，可以去检查代码是否有问题啦~ 当然，也建议隔段时间再执行一次stack命令，再一份获取thread dump，毕竟两次拍片结果（jstack）对比，更准确嘛~</p>

      
    </div>
<div>
  
</div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wan-lei8.gitee.io/2022/01/17/idea%E8%AE%BE%E7%BD%AE%E4%B8%BB%E9%A2%98/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员西桐">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2022/01/17/idea%E8%AE%BE%E7%BD%AE%E4%B8%BB%E9%A2%98/" class="post-title-link" itemprop="url">idea设置主题</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-01-17 17:22:09 / 修改时间：17:36:59" itemprop="dateCreated datePublished" datetime="2022-01-17T17:22:09+08:00">2022-01-17</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h4 id="搜索下载插件"><a href="#搜索下载插件" class="headerlink" title="搜索下载插件"></a>搜索下载插件</h4><h6 id="1-采用离线的方式进行下载离线插件，然后采用IDEA进行导入该插件，重启"><a href="#1-采用离线的方式进行下载离线插件，然后采用IDEA进行导入该插件，重启" class="headerlink" title="1.采用离线的方式进行下载离线插件，然后采用IDEA进行导入该插件，重启"></a>1.采用离线的方式进行下载离线插件，然后采用IDEA进行导入该插件，重启</h6>
          <!--noindex-->
            <div class="post-button">
              <a class="btn" href="/2022/01/17/idea%E8%AE%BE%E7%BD%AE%E4%B8%BB%E9%A2%98/#more" rel="contents">
                阅读全文 &raquo;
              </a>
            </div>
          <!--/noindex-->
        
      
    </div>
<div>
  
</div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wan-lei8.gitee.io/2022/01/17/Map-%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3%E8%A7%A3%E5%86%B3if-else/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员西桐">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2022/01/17/Map-%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3%E8%A7%A3%E5%86%B3if-else/" class="post-title-link" itemprop="url">Map+函数式接口解决if-else</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-01-17 13:45:47 / 修改时间：13:53:06" itemprop="dateCreated datePublished" datetime="2022-01-17T13:45:47+08:00">2022-01-17</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h4 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h4><p>最近写了一个服务：根据优惠券的类型resourceType和编码resourceId来 查询 发放方式grantType和领取规则</p>
          <!--noindex-->
            <div class="post-button">
              <a class="btn" href="/2022/01/17/Map-%E5%87%BD%E6%95%B0%E5%BC%8F%E6%8E%A5%E5%8F%A3%E8%A7%A3%E5%86%B3if-else/#more" rel="contents">
                阅读全文 &raquo;
              </a>
            </div>
          <!--/noindex-->
        
      
    </div>
<div>
  
</div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wan-lei8.gitee.io/2022/01/12/LocalDateTime%E4%BD%BF%E7%94%A8/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员西桐">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2022/01/12/LocalDateTime%E4%BD%BF%E7%94%A8/" class="post-title-link" itemprop="url">LocalDateTime使用</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-01-12 15:06:53 / 修改时间：15:17:56" itemprop="dateCreated datePublished" datetime="2022-01-12T15:06:53+08:00">2022-01-12</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h3 id="LocalDateTime日期格式化"><a href="#LocalDateTime日期格式化" class="headerlink" title="LocalDateTime日期格式化"></a>LocalDateTime日期格式化</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LocalDateTimeSerializerConfig</span> </span>&#123;</span><br><span class="line">    <span class="meta">@org</span>.springframework.beans.factory.annotation.Value(<span class="string">&quot;$&#123;spring.jackson.date-format:yyyy-MM-dd HH:mm:ss&#125;&quot;</span>)</span><br><span class="line">    <span class="keyword">private</span> String pattern;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> LocalDateTimeSerializer <span class="title">localDateTimeDeserializer</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Bean</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Jackson2ObjectMapperBuilderCustomizer <span class="title">jackson2ObjectMapperBuilderCustomizer</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> builder -&gt; builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h4 id="常规使用"><a href="#常规使用" class="headerlink" title="常规使用"></a>常规使用</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">LocalDateTime now = LocalDateTime.now();   <span class="comment">// 2020-01-29T14:35:51.207</span></span><br><span class="line"><span class="keyword">int</span> year = now.getYear();                  <span class="comment">// 2020</span></span><br><span class="line">Month month = now.getMonth();              <span class="comment">// JANUARY</span></span><br><span class="line"><span class="keyword">int</span> monthValue = now.getMonthValue();      <span class="comment">// 1</span></span><br><span class="line"><span class="keyword">int</span> dayOfYear = now.getDayOfYear();        <span class="comment">// 29</span></span><br><span class="line"><span class="keyword">int</span> dayOfMonth = now.getDayOfMonth();      <span class="comment">// 29</span></span><br><span class="line">DayOfWeek dayOfWeek = now.getDayOfWeek();  <span class="comment">// WEDNESDAY</span></span><br><span class="line"><span class="keyword">int</span> dayOfWeekValue = dayOfWeek.getValue(); <span class="comment">// 3</span></span><br><span class="line"><span class="keyword">int</span> hour = now.getHour();                  <span class="comment">// 14</span></span><br><span class="line"><span class="keyword">int</span> minute = now.getMinute();              <span class="comment">// 35</span></span><br><span class="line"><span class="keyword">int</span> second = now.getSecond();              <span class="comment">// 51</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">long</span> seconds = Instant.now().getEpochSecond();    <span class="comment">// 秒时间戳(10位)</span></span><br><span class="line"><span class="keyword">long</span> milliSeconds = Instant.now().toEpochMilli(); <span class="comment">// 毫秒时间戳(13位)</span></span><br><span class="line"></span><br><span class="line">LocalDateTime dateTimeFromSecond = LocalDateTime.ofInstant(</span><br><span class="line">    Instant.ofEpochSecond(seconds), ZoneOffset.ofHours(<span class="number">8</span>)</span><br><span class="line">);  <span class="comment">// 秒转datetime</span></span><br><span class="line"></span><br><span class="line">LocalDateTime dateTimeFromMilliSecond = LocalDateTime.ofInstant(</span><br><span class="line">    Instant.ofEpochMilli(milliSeconds), ZoneOffset.ofHours(<span class="number">8</span>)</span><br><span class="line">); <span class="comment">// 毫秒转datetime</span></span><br></pre></td></tr></table></figure>

<h4 id="各种转换"><a href="#各种转换" class="headerlink" title="各种转换"></a>各种转换</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">String format = LocalDateTime.now().format(</span><br><span class="line">    DateTimeFormatter.ofPattern(<span class="string">&quot;yyyy-MM-dd HH:mm:ss&quot;</span>)</span><br><span class="line">);  <span class="comment">// datetime转字符串</span></span><br><span class="line"></span><br><span class="line">LocalDateTime dateTime = LocalDateTime.parse(</span><br><span class="line">    format,</span><br><span class="line">    DateTimeFormatter.ofPattern(<span class="string">&quot;yyyy-MM-dd HH:mm:ss&quot;</span>)</span><br><span class="line">);  <span class="comment">// 字符串转datetime</span></span><br><span class="line"></span><br><span class="line">Date date = Date.from(dateTime.toInstant(ZoneOffset.ofHours(<span class="number">8</span>)));                             <span class="comment">// datetime转date</span></span><br><span class="line">LocalDateTime fromDate = date.toInstant().atOffset(ZoneOffset.ofHours(<span class="number">8</span>)).toLocalDateTime();  <span class="comment">// date转datetime</span></span><br></pre></td></tr></table></figure>

<h4 id="日期加减"><a href="#日期加减" class="headerlink" title="日期加减"></a>日期加减</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">LocalDateTime dateTime = LocalDateTime.of(<span class="number">2020</span>, <span class="number">1</span>, <span class="number">29</span>, <span class="number">14</span>, <span class="number">35</span>, <span class="number">51</span>); <span class="comment">// 2020-01-29T14:35:51</span></span><br><span class="line"></span><br><span class="line">LocalDateTime localDateTime1 = dateTime.minusSeconds(<span class="number">1</span>);            <span class="comment">// 2020-01-29T14:35:50</span></span><br><span class="line">LocalDateTime localDateTime2 = dateTime.minusMinutes(<span class="number">1</span>);            <span class="comment">// 2020-01-29T14:34:51</span></span><br><span class="line">LocalDateTime localDateTime3 = dateTime.minusHours(<span class="number">1</span>);              <span class="comment">// 2020-01-29T13:35:51</span></span><br><span class="line">LocalDateTime localDateTime4 = dateTime.minusDays(<span class="number">1</span>);               <span class="comment">// 2020-01-28T14:35:51</span></span><br><span class="line">LocalDateTime localDateTime5 = dateTime.minusWeeks(<span class="number">1</span>);              <span class="comment">// 2020-01-22T14:35:51</span></span><br><span class="line">LocalDateTime localDateTime6 = dateTime.minusMonths(<span class="number">1</span>);             <span class="comment">// 2019-12-29T14:35:51</span></span><br><span class="line">LocalDateTime localDateTime7 = dateTime.minusYears(<span class="number">1</span>);              <span class="comment">// 2019-01-29T14:35:51</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>增加的为对应的plus函数，如<code>dateTime.plusSeconds(1)</code></p>
</blockquote>
<h4 id="比较日期"><a href="#比较日期" class="headerlink" title="比较日期"></a>比较日期</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">LocalDateTime now = LocalDateTime.now();     <span class="comment">// 2020-01-29T14:35:51.207</span></span><br><span class="line">LocalDateTime yesterday = now.minusDays(<span class="number">1</span>);  <span class="comment">// 2020-01-28T14:35:51.207</span></span><br><span class="line"><span class="keyword">boolean</span> after = now.isAfter(yesterday);      <span class="comment">// true</span></span><br><span class="line"><span class="keyword">boolean</span> before = now.isBefore(yesterday);    <span class="comment">// false</span></span><br><span class="line"><span class="keyword">boolean</span> equal = now.isEqual(yesterday);      <span class="comment">// false</span></span><br></pre></td></tr></table></figure>

<h4 id="LocalDate日期"><a href="#LocalDate日期" class="headerlink" title="LocalDate日期"></a>LocalDate日期</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">LocalDate dateNow = LocalDate.now();        <span class="comment">// 2020-01-29</span></span><br><span class="line">LocalDate date = LocalDate.of(<span class="number">2020</span>, <span class="number">1</span>, <span class="number">29</span>); <span class="comment">// 2020-01-29</span></span><br></pre></td></tr></table></figure>

<h4 id="LocalTime时间"><a href="#LocalTime时间" class="headerlink" title="LocalTime时间"></a>LocalTime时间</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">LocalTime timeNow = LocalTime.now();       <span class="comment">// 14:35:51.207</span></span><br><span class="line">LocalTime time = LocalTime.of(<span class="number">23</span>, <span class="number">59</span>, <span class="number">59</span>); <span class="comment">// 23:59:59</span></span><br></pre></td></tr></table></figure>


      
    </div>
<div>
  
</div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wan-lei8.gitee.io/2022/01/12/MapStruct%E5%AE%9E%E7%8E%B0%E5%B1%9E%E6%80%A7%E6%98%A0%E5%B0%84/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员西桐">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2022/01/12/MapStruct%E5%AE%9E%E7%8E%B0%E5%B1%9E%E6%80%A7%E6%98%A0%E5%B0%84/" class="post-title-link" itemprop="url">MapStruct实现属性映射</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-01-12 11:34:08 / 修改时间：11:53:24" itemprop="dateCreated datePublished" datetime="2022-01-12T11:34:08+08:00">2022-01-12</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>MapStruct是专门用来处理 domin 实体类与 model 类的属性映射的，我们只需定义 mapper 接口，MapStruct在编译的时候就会自动的帮我们实现这个映射接口，避免了麻烦复杂的映射实现。</p>
<p>为啥不用 <code>BeanUtils</code> 的 <code>copyProperties</code> 方法呢？不也照样可以实现属性的映射么？</p>
<p><code>BeanUtils</code> 就是一个大老粗，只能同属性映射，或者在属性相同的情况下，允许被映射的对象属性少；但当遇到被映射的属性数据类型被修改或者被映射的字段名被修改，则会导致映射失败。</p>
<p>而 <code>mapstruct</code> 就是一个巧媳妇儿了，她心思细腻，把我们可能会遇到的情况都给考虑到了</p>
<h4 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h4><ol>
<li>@Mapper注解</li>
</ol>
<p>从 mybatis3.4.0 开始加入的 @Mapper 注解，目的就是为了不再写mapper映射文件。</p>
<p>我们只需要在 dao 层定义的接口上使用注解就可以实现sql语句的编写，例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Select(&quot;select * from user where name = #&#123;name&#125;&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> User <span class="title">find</span><span class="params">(String name)</span></span>;</span><br></pre></td></tr></table></figure>

<p>如上就是一个简单的使用，虽然简单，但也确实体现出了这个注解的优越性，至少少写了一个xml文件。</p>
<p>MapStruct 的 <code>@Mapper</code> 注解的 <code>componentModel</code> 属性，<code>componentModel</code> 属性用于指定自动生成的接口实现类的组件类型，这个属性支持四个值：</p>
<ul>
<li>default: 这是默认的情况，mapstruct 不使用任何组件类型, 可以通过Mappers.getMapper(Class)方式获取自动生成的实例对象。</li>
<li>cdi: the generated mapper is an application-scoped CDI bean and can be retrieved via @Inject</li>
<li>spring: 生成的实现类上面会自动添加一个@Component注解，可以通过Spring的 @Autowired方式进行注入</li>
<li>jsr330: 生成的实现类上会添加@javax.inject.Named 和@Singleton注解，可以通过 @Inject注解获取</li>
</ul>
<ol start="2">
<li><p>依赖</p>
<p>首先需要把依赖包导入，主要由两个包组成：</p>
<ul>
<li><code>org.mapstruct:mapstruct</code>：包含了一些必要的注解，例如@Mapping。r若我们使用的JDK版本高于1.8，当我们在pom里面导入依赖时候，建议使用坐标是：<code>org.mapstruct:mapstruct-jdk8</code>，这可以帮助我们利用一些Java8的新特性。</li>
<li><code>org.mapstruct:mapstruct-processor</code>：注解处理器，根据注解自动生成mapper的实现。</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependency&gt;</span><br><span class="line">       &lt;groupId&gt;org.mapstruct&lt;/groupId&gt;</span><br><span class="line">       &lt;!-- jdk8以下就使用mapstruct --&gt;</span><br><span class="line">       &lt;artifactId&gt;mapstruct-jdk8&lt;/artifactId&gt;</span><br><span class="line">       &lt;version&gt;<span class="number">1.2</span><span class="number">.0</span>.Final&lt;/version&gt;</span><br><span class="line">   &lt;/dependency&gt;</span><br><span class="line">   &lt;dependency&gt;</span><br><span class="line">       &lt;groupId&gt;org.mapstruct&lt;/groupId&gt;</span><br><span class="line">       &lt;artifactId&gt;mapstruct-processor&lt;/artifactId&gt;</span><br><span class="line">       &lt;version&gt;<span class="number">1.2</span><span class="number">.0</span>.Final&lt;/version&gt;</span><br><span class="line">&lt;/dependency&gt;</span><br></pre></td></tr></table></figure></li>
</ol>
<h4 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h4><ol>
<li><p>定义实体类以及被映射类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 实体类</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@Builder</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">User</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> String createTime;</span><br><span class="line">    <span class="keyword">private</span> LocalDateTime updateTime;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 被映射类VO1:和实体类一模一样</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@Builder</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserVO1</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> String createTime;</span><br><span class="line">    <span class="keyword">private</span> LocalDateTime updateTime;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 被映射类VO1:比实体类少一个字段</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@Builder</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserVO2</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> String createTime;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>定义接口</p>
<p>当实体类和被映射对象属性相同或者被映射对象属性值少几个时：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Mapper(componentModel = &quot;spring&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">UserCovertBasic</span> </span>&#123;</span><br><span class="line">    UserCovertBasic INSTANCE = Mappers.getMapper(UserCovertBasic.class);</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 字段数量类型数量相同，利用工具BeanUtils也可以实现类似效果</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> source</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function">UserVO1 <span class="title">toConvertVO1</span><span class="params">(User source)</span></span>;</span><br><span class="line">    <span class="function">User <span class="title">fromConvertEntity1</span><span class="params">(UserVO1 userVO1)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 字段数量类型相同,数量少：仅能让多的转换成少的，故没有fromConvertEntity2</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> source</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function">UserVO2 <span class="title">toConvertVO2</span><span class="params">(User source)</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ol>
<h4 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestController</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@GetMapping(&quot;convert&quot;)</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Object <span class="title">convertEntity</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        User user = User.builder()</span><br><span class="line">                .id(<span class="number">1</span>)</span><br><span class="line">                .name(<span class="string">&quot;张三&quot;</span>)</span><br><span class="line">                .createTime(<span class="string">&quot;2020-04-01 11:05:07&quot;</span>)</span><br><span class="line">                .updateTime(LocalDateTime.now())</span><br><span class="line">                .build();</span><br><span class="line">        List&lt;Object&gt; objectList = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line"></span><br><span class="line">        objectList.add(user);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 使用mapstruct</span></span><br><span class="line">        UserVO1 userVO1 = UserCovertBasic.INSTANCE.toConvertVO1(user);</span><br><span class="line">        objectList.add(<span class="string">&quot;userVO1:&quot;</span> + UserCovertBasic.INSTANCE.toConvertVO1(user));</span><br><span class="line">        objectList.add(<span class="string">&quot;userVO1转换回实体类user:&quot;</span> + UserCovertBasic.INSTANCE.fromConvertEntity1(userVO1));</span><br><span class="line">        <span class="comment">// 输出转换结果</span></span><br><span class="line">        objectList.add(<span class="string">&quot;userVO2:&quot;</span> + <span class="string">&quot; | &quot;</span> + UserCovertBasic.INSTANCE.toConvertVO2(user));</span><br><span class="line">        <span class="comment">// 使用BeanUtils</span></span><br><span class="line">        UserVO2 userVO22 = <span class="keyword">new</span> UserVO2();</span><br><span class="line">        BeanUtils.copyProperties(user, userVO22);</span><br><span class="line">        objectList.add(<span class="string">&quot;userVO22:&quot;</span> + <span class="string">&quot; | &quot;</span> + userVO22);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> objectList;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="查看编译结果"><a href="#查看编译结果" class="headerlink" title="查看编译结果"></a>查看编译结果</h4><p>通过IDE的反编译功能查看编译后自动生成 <code>UserCovertBasic</code> 的实现类 <code>UserCovertBasicImpl</code> ，内容如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserCovertBasicImpl</span> <span class="keyword">implements</span> <span class="title">UserCovertBasic</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">UserCovertBasicImpl</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> UserVO1 <span class="title">toConvertVO1</span><span class="params">(User source)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (source == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            UserVO1 userVO1 = <span class="keyword">new</span> UserVO1();</span><br><span class="line">            userVO1.setId(source.getId());</span><br><span class="line">            userVO1.setName(source.getName());</span><br><span class="line">            userVO1.setCreateTime(source.getCreateTime());</span><br><span class="line">            userVO1.setUpdateTime(source.getUpdateTime());</span><br><span class="line">            <span class="keyword">return</span> userVO1;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> User <span class="title">fromConvertEntity1</span><span class="params">(UserVO1 userVO1)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (userVO1 == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            User user = <span class="keyword">new</span> User();</span><br><span class="line">            user.setId(userVO1.getId());</span><br><span class="line">            user.setName(userVO1.getName());</span><br><span class="line">            user.setCreateTime(userVO1.getCreateTime());</span><br><span class="line">            user.setUpdateTime(userVO1.getUpdateTime());</span><br><span class="line">            <span class="keyword">return</span> user;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> UserVO2 <span class="title">toConvertVO2</span><span class="params">(User source)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (source == <span class="keyword">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            UserVO2 userVO2 = <span class="keyword">new</span> UserVO2();</span><br><span class="line">            userVO2.setId(source.getId());</span><br><span class="line">            userVO2.setName(source.getName());</span><br><span class="line">            userVO2.setCreateTime(source.getCreateTime());</span><br><span class="line">            <span class="keyword">return</span> userVO2;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="查看结果"><a href="#查看结果" class="headerlink" title="查看结果"></a>查看结果</h4><p><img src="https://img2020.cnblogs.com/blog/1196304/202004/1196304-20200419220449255-1694950350.png" alt="img"></p>
<p>如果是要转换一个集合的话，只需要把这里的实体类换成集合就行了，例如：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">List&lt;UserVO1&gt; <span class="title">toConvertVOList</span><span class="params">(List&lt;User&gt; source)</span></span>;</span><br></pre></td></tr></table></figure>

<h4 id="复制情况"><a href="#复制情况" class="headerlink" title="复制情况"></a>复制情况</h4><ol>
<li><p>类型不一致</p>
<p>实体类我们还是沿用 <code>User</code>；被映射对象 <code>UserVO3</code> 改为：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@Builder</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserVO3</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="comment">// 实体类该属性是String</span></span><br><span class="line">    <span class="keyword">private</span> LocalDateTime createTime;</span><br><span class="line">    <span class="comment">// 实体类该属性是LocalDateTime</span></span><br><span class="line">    <span class="keyword">private</span> String updateTime;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>那么我们定义的接口就要稍稍修改一下了：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Mappings(&#123;</span></span><br><span class="line"><span class="meta">            @Mapping(target = &quot;createTime&quot;, expression = &quot;java(com.java.mmzsblog.util.DateTransform.strToDate(source.getCreateTime()))&quot;),</span></span><br><span class="line"><span class="meta">    &#125;)</span></span><br><span class="line">    <span class="function">UserVO3 <span class="title">toConvertVO3</span><span class="params">(User source)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function">User <span class="title">fromConvertEntity3</span><span class="params">(UserVO3 userVO3)</span></span>;</span><br></pre></td></tr></table></figure>

<p>上面 <code>expression</code> 指定的表达式内容如下:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DateTransform</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> LocalDateTime <span class="title">strToDate</span><span class="params">(String str)</span></span>&#123;</span><br><span class="line">        DateTimeFormatter df = DateTimeFormatter.ofPattern(<span class="string">&quot;yyy-MM-dd HH:mm:ss&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> LocalDateTime.parse(<span class="string">&quot;2018-01-12 17:07:05&quot;</span>,df);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>通过IDE的反编译功能查看编译后的实现类，结果是这样子的：</p>
<p><img src="https://img2020.cnblogs.com/blog/1196304/202004/1196304-20200419222139713-1264721190.png" alt="img"></p>
</li>
</ol>
<p>从图中我们可以看到，编译时使用了expression中定义的表达式对目标字段 <code>createTime</code> 进行了转换；然后你还会发现 <code>updateTime</code> 字段也被自动从 LocalDateTime 类型转换成了 String 类型。</p>
<h4 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h4><p>当字段类型不一致时，以下的类型之间是 <code>mapstruct</code> 自动进行类型转换的:</p>
<ul>
<li>基本类型及其他们对应的包装类型。<br>此时 <code>mapstruct</code> 会自动进行拆装箱。不需要人为的处理</li>
<li>基本类型的包装类型和string类型之间</li>
<li>除此之外的类型转换我们可以通过定义表达式来进行指定转换</li>
</ul>
<h4 id="字段名不一致"><a href="#字段名不一致" class="headerlink" title="字段名不一致"></a>字段名不一致</h4><p>实体类我们还是沿用 <code>User</code>；被映射对象 <code>UserVO4</code> 改为：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@Builder</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserVO4</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 实体类该属性名是id</span></span><br><span class="line">    <span class="keyword">private</span> String userId;</span><br><span class="line">    <span class="comment">// 实体类该属性名是name</span></span><br><span class="line">    <span class="keyword">private</span> String userName;</span><br><span class="line">    <span class="keyword">private</span> String createTime;</span><br><span class="line">    <span class="keyword">private</span> String updateTime;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>那么我们定义的接口就要稍稍修改一下了：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Mappings(&#123;</span></span><br><span class="line"><span class="meta">            @Mapping(source = &quot;id&quot;, target = &quot;userId&quot;),</span></span><br><span class="line"><span class="meta">            @Mapping(source = &quot;name&quot;, target = &quot;userName&quot;)</span></span><br><span class="line"><span class="meta">    &#125;)</span></span><br><span class="line">    <span class="function">UserVO4 <span class="title">toConvertVO</span><span class="params">(User source)</span></span>;</span><br><span class="line">    </span><br><span class="line">    <span class="function">User <span class="title">fromConvertEntity</span><span class="params">(UserVO4 userVO4)</span></span>;</span><br></pre></td></tr></table></figure>

<p>通过IDE的反编译功能查看编译后的实现类，编译后的结果是这样子的：</p>
<p><img src="https://img2020.cnblogs.com/blog/1196304/202004/1196304-20200419224049611-2091880707.png" alt="img"></p>
<p>很明显， <code>mapstruct</code> 通过读取我们配置的字段名对应关系，帮我们把它们赋值在了相对应的位置上，可以说是相当优秀了，但这也仅仅是优秀，而更秀的还请继续往下看：</p>
<h4 id="小结-1"><a href="#小结-1" class="headerlink" title="小结"></a>小结</h4><p>当字段名不一致时，通过使用 <code>@Mappings</code> 注解指定对应关系，编译后即可实现对应字段的赋值。</p>
<h4 id="属性是枚举类型"><a href="#属性是枚举类型" class="headerlink" title="属性是枚举类型"></a>属性是枚举类型</h4><p>实体类我们还是改用 <code>UserEnum</code>:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@Builder</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserEnum</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> UserTypeEnum userTypeEnum;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>被映射对象 <code>UserVO5</code> 改为:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@NoArgsConstructor</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="meta">@Builder</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">UserVO5</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> String type;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>枚举对象是：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Getter</span></span><br><span class="line"><span class="meta">@AllArgsConstructor</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">enum</span> <span class="title">UserTypeEnum</span> </span>&#123;</span><br><span class="line">    Java(<span class="string">&quot;000&quot;</span>, <span class="string">&quot;Java开发工程师&quot;</span>),</span><br><span class="line">    DB(<span class="string">&quot;001&quot;</span>, <span class="string">&quot;数据库管理员&quot;</span>),</span><br><span class="line">    LINUX(<span class="string">&quot;002&quot;</span>, <span class="string">&quot;Linux运维员&quot;</span>);</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">private</span> String value;</span><br><span class="line">    <span class="keyword">private</span> String title;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>那么我们定义的接口还是照常定义，不会受到它是枚举就有所变化：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Mapping(source = &quot;userTypeEnum&quot;, target = &quot;type&quot;)</span></span><br><span class="line">    <span class="function">UserVO5 <span class="title">toConvertVO5</span><span class="params">(UserEnum source)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function">UserEnum <span class="title">fromConvertEntity5</span><span class="params">(UserVO5 userVO5)</span></span>;</span><br></pre></td></tr></table></figure>

<p>通过IDE的反编译功能查看编译后的实现类，编译后的结果是这样子的：</p>
<p><img src="https://img2020.cnblogs.com/blog/1196304/202004/1196304-20200419230431692-1356570810.png" alt="img"></p>
<p>很明显， <code>mapstruct</code> 通过枚举类型的内容，帮我们把枚举类型转换成字符串，并给type赋值，可谓是小心使得万年船啊。</p>

      
    </div>
<div>
  
</div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

      
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://wan-lei8.gitee.io/2022/01/10/bug-record/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="程序员西桐">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          
            <a href="/2022/01/10/bug-record/" class="post-title-link" itemprop="url">bug_record</a>
        </h2>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2022-01-10 14:05:08 / 修改时间：14:08:54" itemprop="dateCreated datePublished" datetime="2022-01-10T14:05:08+08:00">2022-01-10</time>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p><img src="C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220110140637017.png" alt="image-20220110140637017"></p>
<p>数据库对应字段</p>
<p><img src="C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220110140725366.png" alt="image-20220110140725366"></p>
<p>报错：</p>
<p>com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data truncation: Out of range value for column ‘reserve_money’ at row 1</p>
<p>分析：</p>
<p>插入字段长度过长</p>
<p>解决：</p>
<p>修改字段长度</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ALTER TABLE `uc_user_regional_partner` MODIFY COLUMN reserve_money DECIMAL(20,2) NULL COMMENT &#x27;预定金额&#x27;;</span><br></pre></td></tr></table></figure>


      
    </div>
<div>
  
</div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  


  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/"><i class="fa fa-angle-left" aria-label="上一页"></i></a><a class="page-number" href="/">1</a><span class="page-number current">2</span><a class="page-number" href="/page/3/">3</a><span class="space">&hellip;</span><a class="page-number" href="/page/5/">5</a><a class="extend next" rel="next" href="/page/3/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
  </nav>



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt=""
      src="/images/avatar.png">
  <p class="site-author-name" itemprop="name"></p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives">
          <span class="site-state-item-count">41</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/yourname" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;yourname" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="/malegod958@163.com" title="E-Mail → malegod958@163.com"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 2018 – 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">万磊</span>
</div>
  <div class="powered-by">

  </div>

        








      </div>
    </footer>
  </div>

  
  
  <script color='' opacity='0.5' zIndex='-1' count='99' src="/lib/canvas-nest/canvas-nest.min.js"></script>
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

  
	<script type="text/javascript" src="//cdn.bootcss.com/canvas-nest.js/1.0.0/canvas-nest.min.js"></script>
	

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>
<!-- 页面点击小红心 -->
<script type="text/javascript" src="/js/src/clicklove.js"></script>
